C++ a class to be used only by another class
I'm building a class (class A) which needs to be able to create a number of instances of another class (class B) in the course of its operation, but class B is only used by a few member functions of class A, and never used outside of the class. How should class B best be defined? Is it practical / reasonable to make it a private member of Class A? Is this the intended purpose of nested classes, or am I parting with the spirit of the construct?
Thanks, Wyatt
EDIT: On further consideration, I'm not really asking about best practice, as this is for a personal project. I want to include class B as a member of class A from an encapsulation standpoint - it just seems reasonable that a class which is wholly subordinate should in fact be a part of its ow开发者_如何学JAVAning class.
What I'm wondering is whether or not this is a reasonable use-case for nested classes? If not, what is the purpose of nested classes?
One possibility is to define a namespace called detail
inside the namespace where you put your classes. e.g.
// public_namespace_detail.hpp
namespace public_namespace
{
namespace detail
{
class B
{
...
};
}
}
// public_namespace.hpp
#include "public_namespace_detail.hpp"
namespace public_namespace
{
class A
{
detail::B b;
...
};
}
I would just make class B
completely unrelated to class A
-- if nothing else, it's going to make it easier to write tests if you can test class A
and class B
separately. If you don't want to go that route, prevent anyone from instantiating class B
except class A
by defining class B
, making it have a private constructor, and then making class A
a friend
.
You have multiple options :
private inheritance :
class A : private B {};
nested class :
class A { class B { /* etc */ }; };
- Good ol' private member to class B from class A :
class A { B b; };
I personally would go with the nested class if you're 100% sure it's not needed outside.
A general rule of thumb for me is that if I find I have a difficult problem with inheritance then I've probably looked at the problem in the wrong way.
Is there a way you can restructure your program so the classes are less "coupled"? I.E. Can you move the functions out of class A that reference class B (and place them in B)?
I would move it outside of B, since otherwise it will be exposed to other classes via the header file of A (whether you like it or not). Said differently, if you change the implementation of B, then clients of A must recompile - since B was declared inside of A.
The structure of my project should make it clear that the header file for B, should not be used by other classes. For example, I have a folder called "exports" where I place all my header files that I intend to be shared outside the project. Obviously B's header won't be found there.
In a different language that does not use header files, such as C#, I will casually place B inside of A, if B is fairly small - perhaps not more than 6-10 lines of declaration.
Yes, a nested class is fine here.
Note that to keep the code organized, I wouldn't place the definition of B
inside A
. Instead:
class A
{
class B;
};
class A::B
{
};
Among other things, this allows the definition of class A::B
to be placed inside A's implementation file.
EDIT: Since there seems to be some confusion about whether a nested class gets access to the containing class's private members, I provide a code snippet to prove that it does:
class A
{
int x;
class B
{
int func(A* p) { return p->x; }
};
};
- GCC 4.3.4: Accepted.
Variant without inline definition of A::B
, also accepted:
class A
{
int x;
class B;
};
class A::B
{
int func(A* p) { return p->x; }
};
- Comeau: Accepted (both variants)
Your Comeau C/C++ test results are as follows:
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict errors C++ noC++0x_extensions
In strict mode, with -tused, Compile succeeded (but remember, the Comeau online compiler does not link). Compiled with C++0x extensions DISabled.
精彩评论