1

In Primer c++ 5th

Markdown

class A {
    public:
        A() : a(1) {}
        virtual ~A() = default;
    private:
        int a;
};
class B : public A {
    public:
        B() : b(2) {}
    private:
        int b;
};
class C : public B {
    public:
        C() : c(3) {}
    private:
        int c;
};
//class D : public B, public A {                   cause error
//    public:
//        D() : d(4) {}
//    private:
//        int d;
//};

int main()
{

    //A *pa = new C;
    //B *pb = dynamic_cast<B*>(pa);          //1st case
    B *pb = new B;
    C *pc = dynamic_cast<C*>(pb);        //2nd case
    cout << pc << endl;
    //A *pa = new D;
    //B *pb = dynamic_cast<B*>(pa);        //3rd case
}
//output: 0     cast failure

Q1:

Here in the above code .I can understand why the 2nd case doesn't work, but the type of pb-pointed object is B which is the public base class of C .And this is the 2nd situation of what's said in Primer c++.
So why the 2nd case doesn't work while primer c++ said this kind of cast will succeed?

Q2:

the 3rd case. Errors occurred during compilation

error: ‘A’ is an ambiguous base of ‘D’

What does this error mean?

BAKE ZQ
  • 765
  • 6
  • 22
  • That looks like sloppy writing – what matters is the dynamic type of the object, not the static type of the variable. (Did Lippman really write that?) – molbdnilo Mar 23 '19 at 09:04
  • Please ask a question. The post is a bunch of statements, but doesn't currently ask any question. – anatolyg Mar 23 '19 at 09:24
  • @anatolyg add question. – BAKE ZQ Mar 23 '19 at 09:30
  • `class D : public B, public A {` is legal silly useless inheritance: you can't possibly use or refer to the second base – curiousguy Mar 23 '19 at 09:44
  • The error means exactly what it says. `D` is derived from `B` and from `A`. `B` is derived from `A`, so `D` actually derives from `A` via two distinct paths. Effectively this means a `D`'s composition includes two distinct `A`s at separate memory locations. The mapping from `A *` to a `D *` is different for each inherited `A`, so any conversion from `A *` to `D *` (which happens in `A *pa = new D;`) is ambiguous - the compiler has no reason to prefer one way of conversion over the other. – Peter Mar 23 '19 at 10:38
  • This ambiguous passage is also discussed here - https://stackoverflow.com/questions/49381515/is-the-c-primer-making-something-wrong-with-the-usage-of-dynamic-cast – SChepurin Mar 23 '19 at 10:55
  • @SChepurin thanks.one answer states that `type` must be a type of some subobject of the full object of `e`.I can totally understand this.However no one had mentioned about the second cases. – BAKE ZQ Mar 23 '19 at 11:18
  • It produces only warnings when compiled for second case. - "dynamic_cast can also downcast (convert from pointer-to-base to pointer-to-derived) polymorphic classes (those with virtual members) if -and only if- the pointed object is a valid complete object of the target type." With error "an ambiguous base" in third case. – SChepurin Mar 23 '19 at 12:00
  • But if you comment the "virtual..." line, you get "rror: cannot dynamic_cast 'pb' (of type 'class B*') to type 'class C*' (source type is not polymorphic)" – SChepurin Mar 23 '19 at 12:10
  • @SChepurin No warning doesn't mean the cast is succeed.You have to chek if the return pointer by dynamic_cast is not 0 then you can find out if the cast is succeed. – BAKE ZQ Mar 23 '19 at 13:01
  • @BAKE ZQ So, show us the code with the errors generated ("... you can find out if the cast is succeed"). Tired to see the questions without code they talk about. – SChepurin Mar 23 '19 at 13:18
  • @BAKE ZQ - It should return null. "You can't cast a base object to a derived type - it isn't of that type. If you have a base type pointer to a derived object, then you can cast that pointer around using dynamic_cast. – SChepurin Mar 24 '19 at 09:32

1 Answers1

2

in your second example you create a class B, B is a base class for C.

so you can't cast a base class to some derived class.

this will work:

 B *pb = new C();
 C *pc = dynamic_cast<C*>(pb);

regarding 3rd example D derive from B and A, but B also derive from A, this make problems for compiler. you try to derive 2 times for A, the compiler will not know what function A to use, the base A or the derived version of B. al

you should read more about base and derived classes.

Arkady Godlin
  • 588
  • 2
  • 9