c++ namespace and class hierarchy - c++

This is a question that troubles me a for a while, but could not find a the best way to deal with it. I am trying to show this through an example.
I am developing a graphics library with many classes. Some of the classes are "part of" relationship with each other, like these 3 classes:
namespace MyGraphicsLibrary
{
class MatrixStack
{
};
class Transform
{
MatrixStack mMatrixStack;
};
class Renderer
{
Transform mTransform;
};
}
The Renderer class is for users to use, but i did not want them to see Transform, MatrixStack classes when they lookup the MyGraphicsLibrary. The last two classes are only for Renderer class and not for users to use.
Here i am trying to do two things:
Hiding the Transform, MatrixStack classes from users.
Reflect the "part-of" hierarchy of the classes.
I tried the followings to solve this:
The best solution for me would be the private nested-classes, as it would show the user that the nested class is private and also reflects the hierarchy if you simply look at the Renderer class declaration. The following post actually makes me uncertain that is good solution: Pros and cons of using nested C++ classes and enumerations?
I tried to put Transform, MatrixStack into another namespace called Private. So user looking up MyGraphicsLibrary namespace would see Private namespace only covering all classes which are not for the users.
That's good, but there are lot of other classes with the same issue, and i quickly fill the Private namespace with classes which has nothing to do with each other.
Here I could only come up with ugly solutions, like introducing nested namespaces:
namespace MyGraphicsLibrary
{
//private classes belonging to Renderer class
namespace PrivateRenderer
{
class MatrixStack
{
};
class Transform
{
MatrixStack mMatrixStack;
};
}
//public classes for users
class Renderer
{
Transform mTransform;
};
}
Maybe I miss something here, but what do you think which one is the way to go.
Does anybody has a 3rd way?

you can use the PIMPL- (also called opaque pointer) idiom.
with hat you can entirely hide the classes from user the following way:
In your public header (in your include folder):
Renderer.h
class RendererImpl; // forward declaration of internal render structure
//public classes for users
class Renderer
{
public:
Renderer();
~Renderer();
// public interface comes here and delegates all calls to RendererImpl (have to be implemented in cpp)
RendererImpl* renderer; // better use something like QScopedPointer here
};
the cpp:
#include "RendererImpl.h" // your actual renderer that
Renderer::Renderer()
:renderer(new RendererImpl)
{}
Renderer::~Renderer()
{
delete renderer;
}
The implementations may be completely hidden from the API. The headers have to be separated from the real interfaces.

If you want to store Transform as a plain (non-pointer/reference) member, then for the compilation of your public header, its definition should also be visible, because it affects the layout of the container class.
Consequently, the type will be visible wherever you want to use the container class.
You have the following options:
Signal that they are not for public use through naming. Either by putting into a namespace (like detail in boost), or prefixing/suffixing its name.
Use a technique that prevents clients from using that class. Make every member functions private and declare the container class friend. The attorney-client idiom is a more sophisticated way of fine-grained access control.
Store Transform indirectly (pointer or reference), so you do not need its definition in the public header. This is pimpl. A variant of this if the public type is an interface, a base class of the actual Transform implementation.
Unnamed namespace: definitely a bad idea in a header. Unnamed namespaces are like C static: they get a compiler-generated identifier that is guaranteed to be unique to the given translation unit. You will end up with as many distinct Transform types as many places you included its definition.

Use an anonymous namespace:
namespace MyGraphicsLibrary
{
namespace
{
class MatrixStack
{
};
class Transform
{
MatrixStack mMatrixStack;
};
}
class Renderer
{
Transform mTransform;
};
}

Related

CRTP (Curiously Recurring Template Pattern) using a generic base template class instead of the derived class

I have been studying the CRTP lately and have come up of an idea to create a generic base template class using CRTP.
// Example.h
namespace A {
template <class TClass, typename T>
class Example {
public:
Example(T &someStruct) : m_someStruct_(someStruct)
{
}
~Example()
{
DoThis();
}
public:
void DoThis()
{
static_cast<TClass*>(this)->DoThat(m_someStruct_);
}
private:
T m_someStruct_;
};
}
// AsArgument.h
namespace A {
class AsArgument : public Example <AsArgument, SomeStruct> {
friend class Example <AsArgument, SomeStruct>;
private:
void DoThat(SomeStruct &someFun)
{
// Do something to someFun object.
// yehey(someFun);
printf("I want to do that! \n");
}
};
}
My goal is to use the base class object to access the derived class' functions and at the same time, separate the base and derived's implementation by including only the base class' header file and forward declare the derived class as a template argument.
I know the basics of what I can do with incomplete types but I can't seem to find information about templates.
Is it valid to forward declare the class TDerived argument instead of including the header file?
// SomeFile.cpp
#include "Example.h"
class A::AsArgument; // Forward declare this instead of including the AsArgument.h header file
namespace B {
void SomeClass::DoSomething()
{
SomeStruct fun;
Example <AsArgument, SomeStruct> example(fun);
}
}
I am not sure if this is a good design in creating a generic base template class, but my goal after establishing the base class is to easily create derived classes out of it and define the base class implementation on compile time.
It's actually some sort of a combination of RAII and CRTP.
I can actually achieve this by including the "AsArgument.h" file with "Example.h" but the separation between the base and the implementation is lost. And I keep getting compile error when I try to forward declare the AsArgument class (probably because of namespace issues I'm not fully aware of).
Any advise or is this kind of design even efficient and valid?
I'm not really sure what the design goal is here, but the rules about incomplete types apply in the same way whether or not you're talking about templates, you just need to think about where the template is instantiated.
In your case, you are trying to avoid including AsArgument.h in SomeFile.cpp. However, you instantiate the Example class template with the AsArgument class. That means that when you compile SomeFile.cpp, that translation unit does not know anything about the AsArgument class (because it doesn't see its declarations in the .h file), only that it exists.
However, as you might expect, you can't do much with a class if you only know it exists. You can't even hold it by value, since you don't know its size. You can't use any of its interface. In your example, there is no way the compiler can know that AsArgument::DoThat even exists (it doesn't necessarily need to know what it does, that can be left for the linker). Remember that Example is being instantiated in SomeFile.cpp, so that's where the compiler will need to know that DoThat exists.
So you need AsArgument.h. With a normal class, you could just put the declaration in the .h file, and put the definitions (the implementation) in the .cpp file. But AsArgument is a template class, so you can't do that in general. You can only do this for templates if you are templated on a limited number of classes, known in advance, and are willing to explicitly template on all of them.
I can't comment too much on the bigger picture, because I don't know what you are trying to do. I'm not very confident that CRTP is even a fit for you. CRTP is useful for certain things but it's not really the first tool that I turn to. Actually, now that I think of it: I quite rarely use it. In most cases if I'm going to use template based polymorphism, I could just hold the "child" directly and skip the base entirely, in many cases I don't feel like the base buys me enough.
I'd recommend including any compiler errors you have in future SO questions. Good luck!

Declaring a nested class outside of the class it's within?

I have a class whose declaration is getting too bloated for a single header file. I nest classes and structures within it to reinforce their relationship together, so I'd like to keep them together (in the sense that I must use the outermost class's namespace to use the classes within)
Is there a way to declare nested classes from another header file? Or perhaps at least declare the methods of the nested class in another header file? (many methods per class is the reason for the bloat, the number of classes is relatively reasonable at 10)
The structure looks a bit like this:
class Stage{
class Quad{
Quad();
Quad(int width, int height);
// like 20 different constructors, plus methods
private:
glm::vec3 p[4];
};
class Line{
// ...
};
// and a bunch of other classes
// Stage methods
void draw(Quad quad);
void draw(Line line);
// ...
};
I should probably add, I can't expand them inline with the preprocessor, since that messes up my IDE's code completion if I get creative with it.
Is there a way to declare nested classes from another header file?
No, nested classes can only be declared in their surrounding class definition.
Or perhaps at least declare the methods of the nested class in another header file?
Yes, you can just declare the nested classes within their class, then define them later.
class Stage{
class Quad;
class Line;
// and a bunch of other classes
// Stage methods
void draw(Quad quad);
void draw(Line line);
// ...
};
// ... later
class Stage::Quad {
// stuff
};
// ... later still
class Stage::Line {
// whatever
};

Using namespace to isolate hierarchy of classes

I have a fairly large hierarchy of classes derived from a base class Entity. I would like to group these classes into a separate namespace. Currently, this looks like the following:
namespace Entity {
class Entity {
//...
};
class A : public Entity { // Instead of AEntity from before.
//...
};
class B : public Entity { // Instead of BEntity from before.
//...
};
}
int main() {
// Example usage:
Entity::Entity *entity = new Entity::B();
delete entity;
}
Having to write Entity::Entity is a bit unfortunate, so I'm wondering if this is a good idea? Adding using namespace Entity or typedef Entity::Entity Entity in the global namespace doesn't work (as that would conflict with namespace Entity). They could be added within main though...
Should I avoid naming the namespace the same as the base class within it? Or is this common practice?
Should I avoid naming the namespace the same as the base class within it?
I would. As well as the conflict you point out, it makes it awkward to refer to the namespace from within itself (sometimes necessary when names at namespace scope are hidden within a nested scope). Neither issue is particularly serious, but why make life harder than necessary?
You might call the namespace Entities, since it contains multiple entity types; and/or perhaps call the base class Base, since the namespace completes the description of what it's the base of.
I tend to used different naming conventions for namespaces (lower_case) and classes (Capitalised), but that might not suit your aesthetics or arbitrary corporate dictats.

Pimpl with header containing the class

I came across an implementation which had the pimpl class as a header and included that in the pimpl implementation. Does it even make sense? Something like this:
UI.h
class UI {
public:
UI();
virtual ~UI();
// bunch of methods
private:
UIImpl* m_impl;
}
UIImpl.h
class UIImpl
{
public:
UIImpl( ...) ;
......
}
UIImpl.cpp
#include "UIImpl.h"
UIImpl::UIImpl()
{
//Actual Implementation
...
}
I was thinking that the reason for PIMPL was to hide the implementation totally inside the cpp file. Does having a header defeat the purpose?
They're different kinds of header. UI.h is "public" - it's part of the external interface of the library, for use by its clients.
UIImpl.h is "private," just as the UIImpl.cpp is. As long as it's never included in a public header, it can remain invisible to clients, just as the .cpp itself can.
There can be several reasons for splitting the impl class definition into a header file. Perhaps some other implementation classes are passed UIImpl& parameters. Perhaps it's easier to run doxygen on headers only. Perhaps it's just project policy.
The bottom line is, it's still Pimpl, as long as you don't publish the private header.
I was thinking that the reason for PIMPL was to hide the implementation totally inside the cpp file. Does having a header defeat the purpose?
Not necessarily. pIMPL can be used for fast value swapping (probably in architectures before C++11/move semantics), bridge design pattern or any other number of other reasons.
An example of bridge design pattern:
class WinImpl { virtual ~WinImpl() = 0; /* other interfaces here */ };
// different header file(s)
#ifdef WIN32
class WindowsWinImpl: public WinImpl { /* ... */ };
#else
class LinuxWinImpl: public WinImpl { /* ... */ };
#endif
// different header file
class Window { private: WinImpl* pImpl /*= OSWindowFactory::CreateImpl();*/ };
In this case you have a pImpl model, where it is perfectly OK to include the definition of WinImpl in the header of Window class (because the purpose is not to hide the implementation but to abstract it's interface).
It makes perfect sense to do this. It allows the UIImpl.h (and related .cpp) to be modified, without having to change code that is dependent on UI.h. Since the UIimpl class is just stored as a pointer [and presumably the UI itself only has access to public methods of the UIimpl class, nothing about the UIimpl class is known to the UI.h code.
In fact, you probably NEED the "UIimpl.h" to allow the public functionality of the class to be seen by the UI class.
E.g.
class UIImpl
{
public:
UIImpl( ...) ;
void func() { ... }
}
class UI
{
public:
UI();
virtual ~UI();
// bunch of methods
void func() { m_impl->func(); }
...
}
For this to work, UI needs to know the public interface provided by the UIimpl class.
Yes, it does make sense.
An example of use: in code developed for more than one operating system, UI.h would be visible from the operating-system-independent code, but not UIImpl.h. The operating-system-dependent-code (implementation code) would see both headers, UI.h and UIImpl.h

How to restrict the visibility of a class outside the namespace in which it is declared?

I have a namespace in c++ which contains 5 classes. All of them are having public access modifier. Out of these, 2 classes are static classes.
I want to restrict these classes to be visible outside the namespace in which they are declared.
So, like in another namespace, if I import this namespace, then these 2 classes should not be available to use.
There aren't static classes in C++. If by static classes you mean helper classes used by other classes in your code, and are not meant to be used by client code, then you can use unnamed namespace, and define the helper classes inside them.
namespace somespace
{
namespace //it is unnamed namespace
{
class helper
{
//define it here
};
}
class A
{
helper m_helper;
};
}
Boost uses another technique as well. It defines all the helper classes in a namepace called details.
namespace somespace
{
namespace details //it is details namespace
{
class helper
{
//define it here
};
}
class A
{
details::helper m_helper; //use fully-qualified name
};
}
There are 2 possibilities to prevent using classes in c++, first one is to make these classes private and nested inside the class where you go to use them.
class User{
private:
class Internal{};
};
The second possibility is to make the constructor of your class private and declare the friend classes which will be able to use it like:
class Internal{
private:
friend class User;
Internal(){}
public:
//class interface.
};
I would try to put the two static classes in another namespace and make this namespace useable in the implemention files of the other 5 classes.
More ideas possible, if you give minimal example source.