Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Base class 'class A' should be explicitly initialized in the copy constructor [duplicate]

Tags:

c++

qt

I confused by compiler warning. I used MinGW 5.3.0 32bit and i try to compile this code:

#include <QCoreApplication>
#include <QObject>
#include <QDebug>    

class A : public QObject
    {
        Q_OBJECT

    public:
        A(QObject* parent = 0){ Q_UNUSED(parent);}
        ~A() {qDebug()<<"~A()";}

        virtual void func(){}
    private:

    };

    class B : public A
    {
        Q_OBJECT

        public:
            B(){}
            B (const B & object) {/*do somthing*/}
            ~B(){}

            void func(){/*do somthing*/}
    private:

    };

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

        return a.exec();
    }

My compiler tell me:

In copy constructor 'B::B(const B&)': WARNING: base class 'class A' should be explicitly initialized in the copy constructor [-Wextra] B (const B & object) {/do somthing/} ^

Whats wrong?

like image 234
Vladimir Pogonin Avatar asked Apr 25 '17 13:04

Vladimir Pogonin


People also ask

Why do we need explicit copy constructor?

An explicit copy constructor is one that is declared explicit by using the explicit keyword. For example: explicit X(const X& copy_from_me); It is used to prevent copying of objects at function calls or with the copy-initialization syntax.

Can a copy constructor invoked explicitly?

4. It is also called member-wise initialization because the copy constructor initializes one object with the existing object, both belonging to the same class on a member-by-member copy basis. 5. The copy constructor can be defined explicitly by the programmer.

Which is the correct way to call the base class constructor?

To call the parameterized constructor of base class inside the parameterized constructor of sub class, we have to mention it explicitly. The parameterized constructor of base class cannot be called in default constructor of sub class, it should be called in the parameterized constructor of sub class.

When copy constructor is called object should be created and initialized?

The Copy constructor is called mainly when a new object is created from an existing object, as a copy of the existing object. In C++, a Copy Constructor may be called for the following cases: 1) When an object of the class is returned by value.


2 Answers

For a hand-rolled copy constructor (i.e. your B::B(const B &)) it is unusual (although not technically illegal in standard C++) in practice to rely on the default constructor of A being invoked - which is what will happen if you implement the copy constructor of B without explicitly initialising the A in the initialiser list of B constructor.

Your compiler is configured to warn about such things. That is a quality-of-implementation concern for compilers (they are not required to issue warnings in cases like this). But, practically, your compile vendor is doing you a favour.

Your copy constructor of B

B (const B & object) {/*do somthing*/}

is actually equivalent to

B (const B & object) : A() {/*do somthing*/}

which, as I said above, is unusual to explicitly do in practice - it is rarely a desirable behaviour.

The way to shut your compiler up, so it doesn't issue this warning, is to explicitly construct A in the initialiser list of Bs constructor. You could do it like the above using the default constructor of A (which, theoretically, may or may not stop the compiler complaining), but the more usual technique is something akin to

B (const B & object) : A(object) {/*do somthing*/}

Bear in mind that the copy constructor of A will be invoked before the body of B constructors (i.e. base classes are constructed first).

Even better, you would be better off not defining a copy constructor at all, if possible. In that case (assuming something doesn't prevent it from doing so, such as a private copy constructor of a base class) the compiler will automatically generate a copy constructor for B that initialises all its base classes using their copy constructors (recursively) and all its data members.

like image 123
Peter Avatar answered Sep 20 '22 05:09

Peter


The problem here is that your class B inherits from A that itself inherits from QObject class which is not designed to be copyable.

Therefore you cannot call the QObject copy constructor in your class A copy constructor provided you have implemented one.

You can still call the default constructor from A in B copy ctor B (const B & object) : A() or even B (const B & object) : A(object) but it will never construct an exact copy of your object.

See http://doc.qt.io/qt-5/object.html#identity-vs-value for more detailed explanation of Qt's choice.

like image 21
Fryz Avatar answered Sep 22 '22 05:09

Fryz