Copy-constructor of multiply-inherited classes

c++, copy-constructor, inheritance, multiple-inheritance, stl

Solution

Here is what happens in your code:

int main() 
{ 
    vector<Base> v;    // 1
    Base b('b');       // 2
    Child c;           // 3

    v.push_back(b);    // 4
    v.push_back(c);    // 5
    return 0; 
}                      // 6

line 1: vector v constructed

line 2: Base b constructed (calling Base's constructor)

line 3: Child c constructed (calling Child's constructor and Base's constructor)

line 4: v is current at maximum capacity and needs to be resized. Memory is allocated for 1 element of Base by v. Base b copied into v[0] (calling Base's copy constructor).

line 5: v is again at maximum capacity and needs to be resized. Memory is allocated for 2 elements of Base by v. The old v[0] is copied into the new v[0] (calling Base's copy constructor). The old v[0] is deleted (calling Base's destructor ("Base destructor: b")). Child c is copied into v[1] (calling Base's copy constructor).

line 6: c, b, and v run out of scope. Child c is deleted (calling Child's destructor ("Child destructor") then Base's destructor ("Base destructor: c"). Base b is deleted (calling Base's destructor ("Base destructor: b")). Base v[0], v[1] are deleted (calling Base's destructor twice ("Base destructor: b", "Base destructor: c")).

There is no memory leak - for every constructor in the above sequence a corresponding destructor is called.

Additionally, you seem to be very confused about copy constructors. Child c gets passed to push_back as a Base& - which then calls Base's copy constructor as expected. Since Base's implicit copy constructor is not virtual or overriden, having Child derive from uncopyable does nothing to change this.

Note that a `vector<Base>` cannot ever store an object of type Child; it only knows to allocate enough memory for a Base. What occurs when assigning an instance of Child to a Base is known as slicing, which, while often unintended and misunderstood, seems like it may actually be what you want in your described scenario.

Problem

Consider this piece of code: ``` #include <vector> #include <iostream> using namespace std; class Base { char _type; public: Base(char type): _type(type) {} ~Base() { cout << "Base destructor: " << _type << endl; } }; class uncopyable { protected: uncopyable() {} ~uncopyable() {} private: uncopyable( const uncopyable& ); const uncopyable& operator=( const uncopyable& ); }; class Child : public Base, private uncopyable { int j; public: Child(): Base('c') {} ~Child() { cout << "Child destructor" << endl; } }; int main() { vector<Base> v; Base b('b'); Child c; v.push_back(b); v.push_back(c); return 0; } ``` The output on my system is: ``` Base destructor: b Child destructor Base destructor: c Base destructor: b Base destructor: b Base destructor: c ``` My questions are: Why is the destructor of `Base` (with type b) called three times instead of two (do we have more than two copies of object b)? What happens when we copy an object of type `Child`, considering the copy-constructor of one of its parents is private. Is it undefined behavior? I was expecting to get a compile-time error whenever I try to copy an object of type `Child`. I thought the child's default copy-constructor would try to call the private copy-constructor of the Uncopyable class and cause compilation error. Why doesn't it give compile errors? The reason the code is designed this way is because the `Child` class is huge. The desired behavior is throwing away the child data whenever a client tries to copy a `Child` object (calling the destructor of `Child` without calling the destructor of `Base`). This piece of code achieves that, but I guess it results in undefined behavior and has memory leak (never calls the destructor of `Child` for the copied instance).

Original source

Related problems