наследование конструкторов

Точнее наследование классов и как быть с констукторами родителя. Надо их переопределять или нет и  как переопределять и т.д.

Вот наш общий пример с классом A, у которого есть явный конструктор по умолчанию, явный конструтор копирования и оператор тоже явны присваивания (явный это который написан нами, а не по умолчанию используемы компилятором, хотя вобщем-то это не важно).

Теперь нам нужно развить класс A, добавить новую функциональность, то есть унаследоваться от класса A и создать потомок например класс B.

Класс А нам уже нельзя менять, допустим это вообще не наш класс, а например из исходников QtSources.

class A
{
public:
    A() // конструктор по умолчанию обычный
    {
        qDebug() << "A() this:" << this << " // easy default ctor";
    }
    A(const A& in) // конструктор по умолчанию копирования
    {
        qDebug() << "A(const A& in) " << " this:" << this << " // default copy ctor";
    }
    A& A::operator=(const A &cl)
    {
        qDebug() << "A& A::operator=(const A &cl) // assignment operator";
        return *this;
    }
    ~A()
    {
        qDebug() << "~A " << this;
    }
};

class B : public A
{
    public:

};

void foo()
{
    A clA;

    B clB (clA);   // error: cannot convert parameter 1 from 'A' to 'const B &'

    B clB = clA;    //  cannot convert from 'A' to 'B'

    B clB;
    // clB = clA; // no operator found which takes a right-hand operand of type 'A' (or there is no acceptable conversion)

    qDebug() << "<- foo()";
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "--------main()---------";

    qDebug() << "-> foo()";
    foo();
    qDebug() << "return from foo()";
    return a.exec();
}

Получаем ошибки компиляции при создании класса B с передачей в качестве исходника класса A в разных вариантах конструкторов класса B.

И получается, что нам в результате надо для класса B реализовать как и в классе А такие же конструкторы копирования, оператор присваивания и самое интересное также конструктор обычный по умолчанию и тогда только все скомпилируется без ошибок.

class B : public A
{
    public:
    B():A() // конструктор по умолчанию обычный
    {
        qDebug() << "B() this:" << this << " // easy default ctor";
    }
    B(const A& in):A(in) // конструктор по умолчанию копирования
    {
        qDebug() << "B(const B& in) " << " this:" << this << " // default copy ctor";
    }
    B& B::operator=(const B &cl)
    {
        qDebug() << "B& B::operator=(const B &cl) // assignment operator";
        return *this;
    }
};

Тут надо отметить, что мы не забываем в конструкторах класса B вызывать конструктор класса A , например так:

B(const A& in) : A(in) 

Далее пробуем вызвать конструктор копирования класса B:

void foo()
{
    A clA;

    B clB (clA);
.....

И получаем как и ожидали в консоль (тут все понятно):

--------main()---------
-> foo()
A() this: 0xe9fcca  // easy default ctor
A(const A& in)   this: 0xe9fccb  // default copy ctor
B(const B& in)   this: 0xe9fccb  // default copy ctor
<- foo()
~A  0xe9fccb
~A  0xe9fcca
return from foo()

Далее пробуем вызвать оператор присваивания для класса B:

A clA;
B clB2;
clB2 = clA;

И тут происходит немного не так как ожидалось:

--------main()---------
-> foo()
A() this: 0x12ff98a  // easy default ctor
A() this: 0x12ff98b  // easy default ctor
B() this: 0x12ff98b  // easy default ctor
A(const A& in)   this: 0x12ff989  // default copy ctor
B(const B& in)   this: 0x12ff989  // default copy ctor
B& B::operator=(const B &cl) // assignment operator
~A  0x12ff989
<- foo()
~A  0x12ff98b
~A  0x12ff98a
return from foo()

Выше происходит создание трех экземпляров класса А, причеи один уничтожается еще до выхода из функции foo. Такое поведение отлично от поведения если бы был только класс А.