1

Could someone explain this to me:

struct A {
    virtual ~A() = default;
};

struct B : private A {
    void foo() {
        B* b = new B;
        std::list<A*> list = {b};
        B* back = dynamic_cast<B*>(list.back());
        std::cout << back << std::endl;
    }
};

int main() {
    B b;
    b.foo();  // nullptr
}

From what I understand, only B is aware that B is derived from A. foo() is a member function of B. So dynamic_casting from A* to B* should be fine inside B::foo(). So why is the result nullptr? Same thing goes if it is protected inheritance. Change the inheritance to public, and everything is fine. What's going on here?

prestokeys
  • 4,817
  • 3
  • 20
  • 43

1 Answers1

3

The way dynamic_cast<T>(v) executes its run-time checks is specified in §5.2.7 [expr.dynamic.cast]/p8:

If C is the class type to which T points or refers, the run-time check logically executes as follows:

  • If, in the most derived object pointed (referred) to by v, v points (refers) to a public base class subobject of a C object, and if only one object of type C is derived from the subobject pointed (referred) to o by v the result points (refers) to that C object.
  • Otherwise, if v points (refers) to a public base class subobject of the most derived object, and the type of the most derived object has a base class, of type C, that is unambiguous and public, the result points (refers) to the C subobject of the most derived object.
  • Otherwise, the run-time check fails.

Note that the check only succeeds for public bases.

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • Ok, thanks. Rules are rules I guess. Then I think the definition of private inheritance should include the above rule, because the definitions I read misled me otherwise. – prestokeys Aug 31 '14 at 05:41