bcmpinc
bcmpinc

Reputation: 3370

How to make a debuggable file scoped (static?) class in c++?

I define a lot of classes in my cpp files. Often with unimaginative names, such as 'Implementation'. and am worried about name collisions, as these are horrible to debug (assuming the compiler silently drops one of the definitions). However, I also want to be able to debug my program, so anonymous namespaces are not an option. So, can file-scoped (aka. translation-unit scoped) classes be defined in c++ without using namespaces? If yes, how?

File-scoping in c
In c, one can create a global variable with int foo;, and limit the variable to file-scope using static int foo;. Similarly, file-scoped functions are also created with the static keyword, for example static void bar();. And structs do not define data or executable code, and thus are effectively always file-scoped.

Virtual member functions
Now c++ introduced virtual member functions, which caused structs (aka. classes) to contain data and executable code. Hence structs are now globally defined. However, it is not allowed to use static to make the struct file-scoped again. I.e. static struct Foo{}; does not compile.

Namespaces
To tackle the problem of name collisions, c++ also introduced named namespaces. Those can also be used to wrap the struct, such that it becomes pseudo-file-scoped. Though this still forces you to pick a unique name (that you don't even care about) for every file. As a solution, they also introduced anonymous namespaces. Unfortunately, neither gdb nor the visual studio debugger seem to support anonymous namespaces (it is basically impossible to refer to anything inside the anonymous namespace).

Upvotes: 0

Views: 95

Answers (1)

bcmpinc
bcmpinc

Reputation: 3370

A partial solution is to use anonymous structs/classes and typedef these, as both are file-scoped (C - Limit struct Scope), except that it is impossible to explicitly define constructors or destructors (Constructor for a no-named struct). The following example compiles and runs fine with gcc and also allows gdb to put a breakpoint on method():

interface.h:

struct Iface {
  virtual void method()=0;
};

implementation_a.cpp and implementation_b.cpp:

#include "interface.h"
typedef struct : Interface {
  virtual void method();
} Implementation;
void Implementation::method() {
  // Do stuff...
}
Interface * new_implementation_a() { // or new_implementation_b
  return new Implementation();
}

main.cpp:

#include "iface.h"
int main() {
  Interface * a = new_implementation_a();
  Interface * b = new_implementation_b();
  a->method();
  b->method();
  return 0;
}

Upvotes: 1

Related Questions