10

I'm not sure if I'm missing something here but it seems that the following code (a similar one can be found into another answer I can no longer find, the question here is different by the way) is compiling just fine for clang and not compiling for gcc

#include <iostream>
using namespace std;

class base {
public:
 base(int i) {};

private:
 base(){};
};

class derivedA: virtual public base {
public:
 derivedA(int i) : base(i) {};

protected:
  derivedA() : base(0) {};
};

class derivedB: virtual public base {
public:
 derivedB(int i) : base(i) {};

protected:
  derivedB() : base(0) {};
};

class derivedAB : public derivedA, public derivedB {
public:
 derivedAB(int i) {};
 virtual ~derivedAB() = 0;
};

derivedAB::~derivedAB() {};

class lastDerived : public derivedAB {
public:
    lastDerived() : base(1), derivedAB(0) {};
};

int main(){
        lastDerived obj;
}

gcc is reporting

main.cpp: In constructor 'derivedAB::derivedAB(int)':
main.cpp:9:2: error: 'base::base()' is private
  base(){};

Which one is the correct behavior? I'd say gcc's one but I'm not sure why.

Marco A.
  • 43,032
  • 26
  • 132
  • 246
  • 1
    What `return 0;`? `main` doesn't need a return statement. – ecatmur Jul 02 '14 at 17:13
  • Further discussion: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#257 – Brian Bi Jul 02 '14 at 17:37
  • 1
    Also related: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=19249 – Brian Bi Jul 02 '14 at 17:38
  • 1
    In case anyone is wondering VS2013 reports the same error as gcc – Silvester Jul 02 '14 at 17:54
  • What if later derivedA/derivedB changes and someone add to derivedA and derivedB classes a constructor with side effects? Not very maintenable. That would require to fix derivedAB potentially breaking all code using lastDerived or derivedAB (without compiler errors for that!) – CoffeDeveloper Oct 25 '14 at 18:32

1 Answers1

12

A virtual base class of an abstract class does not need to be initialized in the mem-initializer-list of a constructor of that abstract base class.

This is discussed in 12.6.2p8:

[...] and the entity is not a virtual base class of an abstract class [...]
[ Note: An abstract class (10.4) is never a most derived class, thus its constructors never initialize virtual base classes, therefore the corresponding mem-initializers may be omitted. — end note ]

So clang is correct, and gcc is incorrect. This would be different were derivedAB not abstract.


This is a new allowance in C++11, since DR 257; g++ is correct for C++03. There is a gcc bug at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=19249; perhaps it could do with poking.

ecatmur
  • 152,476
  • 27
  • 293
  • 366