1.2.4.3 copy ctor
  • copy ctor(assignment ctor) and slicing. Below four are all SLICING. number 5 and number 4 is not very obvious. They are call base class ctor. No matter what you input a reference to a derived class or not.
    class Base{}; 
    class Derived1 : Base{}; 
    class Derived2 : Base{}; 
    Derived1 d1; 
    Derived1 d2; 
    ///////////////////// 
    Base b = d1; //1) 
     
    Fun(Base b); 
    Fun(d1);  //2) 
     
    Base& Bref = d1; 
    Fun(Bref) //3) 
     
    Base* bp = new B(Bref); //4) 
     
    Base* bp1 = new Derived1();  //5) sibling slicing 
    base* bp2 = new Derived2(); 
    *bp1 = *bp2;  // bp1 just copy Base part in Derived2. 
    //so bp1 now is MIXTURE of d1 and d2.
  • Think a problem as below.
    class Base{}; 
    class Derived1 : Base{}; 
    class Derived2 : Base{}; 
    Derived d1; 
    Derived d2; 
     
    Base* Copy(Base& Bref){ 
    //How to avoid slicing and make deep copy. 
    } 
     
    Base& Bref = d1 
    Base* d1p = Copy(Bref) 
     
    Base& Bref = d2 
    Base* d2p = Copy(Bref)
  • Continue- Think this problem: error method
    Base* Copy(Base& Bref){ 
    Base* p = new Base(Bref) 
    //Slicing happen. bad 
    }
  • Continue- Think this problem: TypeID method.
    Base* Copy(Base& Bref){ 
    //Use tyid and dynamic_cast 
    //involve a lot of if and switch about type. 
    //anytime if you use dynamic_cast and if, 
    //you can think about virtual function 
    }
  • Continue- Think this problem: Virtual Clone method. A function’s return type is never considered part of its signature. You can override a member function with any return type as long as the return type could be used wherever the base class return type could be used.
    class Base{ 
      virutal Base* Clone() = 0; 
    }; 
     
    class Derived1 : Base{ 
        virutal ____________Derived1* Clone(){return new Derived1(*this);} 
    } 
     
    Base* Copy(Base& Bref){ 
    Base* p = Bref.Clone(); 
    }
  • Continue- Think this problem: Change Design. Base is concrete class, More Effective C++ Item 33 said"Making Non-leaf class abstract. So maybe you can change the inheritance system.
  • Assignment operator and copy ctor in inheritance:
    1. Default Assignment operator and copy constructor in derived class which are implicitly produced by compiler will call default base assignment operator and copy constructor.
    2. If derived class has no new operation. Don’t need to define derived class Assignment operator and copy constructor, implicit one will call base one automatically
    3. If derived class has new operation. You have to define derived class Assignment operator and copy constructor, it will not invoke assignment operator and copy constructor in base class any more. Inside, manually invoke base class Assignment operator and copy ctor Detail can be found in C++ primer p760. Syntax looks like below: see effective C++ Item 16.
    4. For copy ctor, just init list syntaxt. For assignment operator, use two different methods depends on if base class declare its own assignment operator(). Source code is below:
      DerivedClass::DerivedClass(const DerivedClass &dc): \ 
      BaseClass(dc){...}  //init list syntax here. 
       
      DerivedClass & DerivedClass::operator=(const DerivedClass &dc){ 
      BaseClass::operator=(dc); 
      // base class declare explicitly operator 
       
      ( (BaseClass&) *this ) = dc 
      //base class no explicitly operator 
      // change *this to BaseClass reference, 
      // if you change to BaseClass, It will call copy ctor. 
      }