I am maintaining a large code base and am using a combination of forward declarations and the pImpl idiom to keep compile times down and reduce dependencies (and it works really well,)
The problem I have is with classes that contain public enumerations. These enumerations cannot be forward declared so I am left with no option but to include the class header. For example:
// Foo.h
class Foo
{
public:
enum Type
{
TYPE_A,
TYPE_B,
};
...
};
// Bar.h
#include "Foo.h" // For Foo::Type
class Bar
{
public:
void someFunction(Foo::Type type);
...
};
So, I'm looking for ways to avoid this and can only think of the following:
Move the class enumerations to a separate 'types' namespace
开发者_Go百科// FooTypes.h
namespace FooTypes
{
enum Type
{
TYPE_A,
TYPE_B,
};
}
// Bar.h
#include "FooTypes.h"
class Bar
{
public:
void someFunction(FooTypes::Type type);
...
};
Use int instead of the enumeration
// Bar.h
class Bar
{
public:
void someFunction(int type);
...
};
What have I missed? How do other people get around this limitation (not being able to forward declare enumerations.)
Put the enumeration in the class containing the PIMPL.
Put the enumeration into its own type:
struct FooEnum
{
enum Type
{
TYPE_A,
TYPE_B,
};
};
Then Foo
and Bar
can both access FooEnum::Type
and Bar.h
doesn't need to include Foo.h
.
I'd argue that enums are a bad idea to start with, but in general for constants/the many things like constants in C++ none of which are quite constants and all of which have issues. I like to put it into a struct then have the classes using it inherit from the struct.
I'd also argue that the pimpl idiom is bad. Actually I am sure it's a poor way to do things. It's something that works but is awkward and a bit silly. It's also easy to avoid, and the only reason it comes about is due to people using yet other bad design choices.
Usually someone just tacks on OOP stuff to a class they designed to be concrete. Then you get the mixed inheritance case and the plethora of issues it causes such as super slow compile time. Instead, consider pure virtual base classes, then writing your libs to that to avoid templates and avoid the forward declaration problem. Not for everything, but definitely for the cases where you are generating code for lots of classes.
精彩评论