问题
I changed my C++ base class to be protected
inheritance and my dynamic_cast
(s) stopped working.
Why should changing the inheritance to protected
change the behavior of dynamic_cast
?
struct Base {
static Base *lookupDerived(); // Actually returns a Derived * object.
};
struct Derived : protected /* Switch this to public to get it working */ Base {
static void test() {
Base *base = lookupDerived();
if (dynamic_cast<Derived *>(base)) {
std::cout << "It worked (we must be using public inheritance)." << std::endl;
} else {
std::cout << "It failed (we must be using protected inheritance)." << std::endl;
}
};
回答1:
You as an outside user cannot access the protected or private members of a class. The same applies to protected or private inheritance. The authors of a class don't want outside users to access protected/private parent classes any more than they want outside users to access protected/private members.
One reason: Suppose the parent class has a non-virtual destructor. Deleting from an instance derived class from a base class pointer would result in undefined behavior. Making the parent class protected/private means you can't do this (see footnote).
Another reason: Suppose the authors of the class in question don't want outside users to have access to the public members of the parent class. One could use public inheritance (is-a) and demote those public interfaces to protected or private, but this would violate the Liskov substitution principle. Protected or private inheritance is not an is-a relationship. Those public methods become protected or private with protected or private inheritance. There's no problem with Liskov substitution because protected/private inheritance is not is-a.
Footnote: There is an ugly way around this: Use C-style casts. Outside users can cast a
derived class pointer to a base class pointer, even if the base class is not accessible. To me, that's yet another reason to compile with -Wold-style-cast -Werror
.
回答2:
When you change your inheritance to protected, the relationship between your two classes is hidden from the exterior of the object.
回答3:
Private (or proctected) inheritance is semantically different from public inheritance. It is not a "is-a" relationship but a "implemented in terms of" relationship. Meaning that you cant use a base class as a handle to a derived object.
来源:https://stackoverflow.com/questions/12765174/why-does-protected-inheritance-cause-dynamic-cast-to-fail