Let's say I have 2 classes that I want to be visible (within a given header file) and one class that is their ancestor, which one I want to be visible only to the previously mentioned two. How can I achieve such class functionality of being invisible in C++?
问题:
回答1:
Abusing a class
to act as a namespace
will do this. I do not recommend this pattern.
class hidden_stuff {
private: // hide base from everyone
struct base {
// contents
};
public:
class derived1;
};
typedef class hidden_stuff::derived1 derived1;
class hidden_stuff::derived1
: private hidden_stuff::base {}; // private inheritance required
// or hidden_stuff::base is accessible as derived1::base
The real solution (though not technically satisfying the question)
A preferable solution would be to use a clearly-named namespace
such as impl::
or detail::
, which will convey to users that they shouldn't use any classes inside, and stop any possible undesired effects on overloading or the like. That's how most libraries (even Standard Library implementations) "hide" classes from the user.
回答2:
It is not possible.
C++ requires that a class be fully defined at the point it is used as a base, and because of its include mechanism anything that is fully defined at the point of definition of a class is necessarily visible to all who can see the definition of said class.
C++ has mechanisms to protect against Murphy (accidents) but not against Machiavelli (hacks).
That being said, the purpose is itself dubious, the only reason I can fathom would be to prevent the user from relying on the fact that your Derived
class derives from this Fantom
base. Well, deriving privately: class Derived: private Fantom {};
or using composition instead class Derived { private: Fantom _fantom; };
would both achieve this.
回答3:
Instead of hiding class, I'd recommend diabling making use if it. In example:
class Hidden
{
private:
friend class Exposed;
Hidden() {}
int hidden_x;
};
class Exposed : private Hidden
{
public:
Exposed() : Hidden() {}
void DoStuff() { printf( "%d" , hidden_x ); }
};
So what you can: - create any number of Exposed class instances in your code - call DoStuff() method from these instances
But you cannot: - instantiate Hidden class (private constructor) - operate on Hidden class members directly or via Exposed class (they are private)
回答4:
A variation of Anonymous answer, instead of private inheritance you can add private member of the hidden class.
class Hidden
{
private:
friend class Exposed;
Hidden() {}
int hidden_x;
};
class Exposed
{
public:
Exposed() {}
void DoStuff() { printf( "%d" , hidden.hidden_x ); }
private:
Hidden hidden_;
};