0

Consider the following C++ code:

#include <iostream>

using std::cout;

class A
{
public:
    int a;

    A():a(0)
    {
        cout << "A constructor\n";
    }

    virtual void f()
    {
        cout << "f inside A\n";
    }
};

class C : public A
{
public:
    int c;

    virtual void f()
    {
        cout << "f inside C\n";
    }

    C():c(0)
    {
        cout << "C constructor\n";
    }
};

int main()
{
    A varA = C();

    cout << "Size of C class: " << sizeof(C) << "\n";
    cout << "Size of varA object: " << sizeof(varA) << "\n";

    C* varC = static_cast<C*>(&varA);
    varC->f();

    cout << "varC->a is " << varC->a << "\n";
    cout << "varC->c is " << varC->c << "\n";
}

The output of this program is:

A constructor
C constructor
Size of C class: 16
Size of varA object: 8
f inside A
varC->a is 0
varC->c is 1726166356

I initialize the varA object with the constructor of class C. Constructors of A and C class are called, but the varA is a simply a A object. I cast the address of varA to C* type and I try to call its f() function, but it prints the f() function of class A, so I deduce that it is use the early binding mechanism to call it. I think if I call the constructor of derived class, like this case, I obtain the same object if I had called the base constructor. I think the only difference is the other constructors are called. Is my supposition right or there are any other differences?

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
Radioga
  • 416
  • 1
  • 5
  • 16
  • Why are you casting an instance of A to a C (or C*)? All you have is an instance of A. I would assume that your `static_cast` call is not allowed/not defined. – Micha Wiedenmann Dec 14 '16 at 14:54
  • I cast A to C to check the b and c members. – Radioga Dec 14 '16 at 14:58
  • 1
    @Dag - The problem is that an `A` doesn't *have* any members `b` and `c`, because it *is* an `A`. When assigning from a `C` value, you just [slice off](http://stackoverflow.com/questions/274626/what-is-object-slicing) the `A` part and discard the rest of the `C` object. – Bo Persson Dec 14 '16 at 15:02
  • 1
    @Dag No, you cannot cast A to C. You have a A instance (not a C instance), your cast cannot create a C out of your A instance. If you would use dynamic_cast, some compilers even warn, that this cast will never succeed: http://cpp.sh/6fhqm. See also http://en.cppreference.com/w/cpp/language/static_cast Explanation 2. – Micha Wiedenmann Dec 14 '16 at 15:05

2 Answers2

4

Classic example of slicing. A varA = C(); leaves you with object of static and dynamic type of A. As a result, C* varC = static_cast<C*>(&varA); exhibits undefined behavior.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
1

You can store a complete derived class in a base-class pointer, however:

int main() {        
  A* varA = new C();
  C* varC = static_cast<C*>(varA);
  varC->f();

  cout << "varC->a is " << varC->a << endl;
  cout << "varC->b is " << varC->b << endl;
  cout << "varC->c is " << varC->c << endl;
} // oops, forgot to delete varA/varC, memory leak!
Jack Deeth
  • 3,062
  • 3
  • 24
  • 39