Initialization of base class in derived's copy constructor initialization list

Compiling the following minimal.cpp with g++ 6.3.0 like so:

$ g++ -Wall -Werror=extra minimal.cpp -o minimal

If the base constructor in the initializer list of Derived's copy constructor remains commented out, the compiler issues the following:


error: base class ‘class Base’ should be explicitly initialized in the copy constructor [-Werror=extra]
Derived<value>::Derived(Derived<value> const &)
^~~~~~~~~~~~~~
cc1plus: some warnings being treated as errors


Uncommenting it suppresses the warning / error. I am aware of the role -Wall and -Werror=extra plays, and I'd like to keep those flags.

My question is which is actually correct? Is the compiler merely being overly neurotic? Does the standard require the base constructor to be invoked? If it does not require it to be invoked, but the compiler does, does a best practise encourage calling it anyways? The reason I ask is an upstream project's code is generating such a warning which is easily suppressed with a trivial patch calling the base constructor in the copy constructor's initializing list, but upstream refuses to accept it because they believe the compiler is "wrong".

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

class Base
{
    public:
    
        Base() = default;
        Base(Base const &);
};

template <int value>
class Derived : Base
{
    public:

        Derived() = default;
        Derived(Derived<value> const &other);
};

template <int value>
Derived<value>::Derived(Derived<value> const &)
//    : Base()
{

}

int main()
{
    Derived<5> d5;
    Derived<5> d5b(d5);
}
Last edited on
I think in most cases one would want to call the base class copy constructor from the derived class copy constructor but it is easy to forget so I guess that is why they warn you. In your example it doesn't matter because the base doesn't contain any data, but it doesn't hurt either, so it's probably a good habit to do it anyway, don't you think?

1
2
3
4
5
6
template <int value>
Derived<value>::Derived(Derived<value> const& other)
    : Base(other)
{

}


It doesn't force you to call the copy constructor, because in some rare cases you might want to use another constructor, but you will have to do it explicitly. I don't think this is necessary a bad thing because it makes your intent obvious, otherwise someone reading the code might start to wonder if not calling the base class copy constructor is intentional or a mistake.

This is nothing that the C++ standard mandates. It's just one of the warnings that comes with -Wextra.
Last edited on
You'll get the same behaviour whether line 21 is commented or not. However, that's incorrect as you should call the copy constructor of the base class.
1
2
3
4
5
Derived::Derived(Derived const &foo)
   : Base(foo)
{
//...
}
Thanks folks. I suspected that it was a best practise to invoke the base class constructor in the derived constructor's initialization list, even if it's not required by the standard.
Topic archived. No new replies allowed.