// Code to show the implicitly defined code for a class // ***not designed to be compiled!*** class A { // assume details in here -- non-trivial class }; class D { // assume details in here -- non-trivial class }; class B : public A { private: int i; D d; }; // The above is the same as // Additional note: all such declared methods will be "noexcept" if // all of the functions/methods they call are also "noexcept." class B : public A { public: // implicit default constructor: // compiler-generated iff NO constructors (of any form) declared // AND A and D have default (no-arg) constructors B() : A(), d() { } // implicit destructor: // compiler-generated iff NO destructor declared ~B() { } // implicit copy constructor: // compiler-generated iff NO user-declared copy constructor // AND no user-declared (even by =default) move constructor // AND no user-declared (even by =default) move assignment op // AND A and D have copy constructors B(const B &b) : A(b), d(b.d), i(b.i) { } // implicit copy assignment op: (const version) // compiler-generated iff NO user-declared copy assignment op // AND no user-declared (even by =default) move constructor // AND no user-declared (even by =default) move assignment op // AND A and D have assignment ops with const args B &operator=(const B &b) { A::operator=(b); d = b.d; i = b.i; } // implicit copy assignment op: (non-const version) // compiler-generated iff NO user-declared copy assignment op // AND no user-declared (even by =default) move constructor // AND no user-declared (even by =default) move assignment op // AND A or D have assignment ops with non-const args B &operator=(B &b) { A::operator=(b); d = b.d; i = b.i; } // implicit move constructor: // compiler-generated iff NO user-declared move constructor // AND no user-declared (even by =default) copy constructor // AND no user-declared (even by =default) copy assignment op // AND A and D have move constructor B(B &&b) : A(static_cast(b)), d(static_cast(b.d)), i(b.i) { } // implicit move assignment op: // compiler-generated iff NO user-declared move assignment op // AND no user-declared (even by =default) copy constructor // AND no user-declared (even by =default) copy assignment op // AND A and D have move assignment ops B &operator=(B &&b) { A::operator=(static_cast(b)); d = static_cast(b.d); i = b.i; } // other notes // arrays (using [] syntax) would be copied or moved using the // relevant copy/move op // almost all STL classes have copy/move ops defined for them // (those that don't have good reason -- like ios_base) // i.e. vector, list, array, etc all copy & move just fine // all operations are done in the order: // - base class(es), in order declared on the "class C : ..." line // - members, in the order declared in the class definition // all this still holds on structs too private: int i; D d; }; // an use "=default" or "=delete" to cause an implicit member to // be generated (even if otherwise it would not) or to make sure that // an implicit member is not generated // can declare type of method *slightly* differently to change // explicit, virtual, public/protected/private, volatile // (and maybe something else?) no default args allowed class E { public: virtual ~E() = default; // makes destructor virtual (unlike normal) // and uses implicit destructor code E(const E &) = default; // makes the implicit copy constructor // also blocks the implicit move constructor, because this // is user declared (see above) E &operator=(const E &) = delete; // removes assignment op };