Reputation: 871
The following code fails to compile with this error with g++ and a similar error with clang.
main.cpp:16:19: error: 'QByteArray' is a private member of 'QByteArray'
Container2(const QByteArray &ba);
^
main.cpp:3:18: note: constrained by private inheritance here
class Container1:private QByteArray
^~~~~~~~~~~~~~~~~~
../edge-clang/qt5/include/QtCore/qbytearray.h:167:21: note: member is declared here
class Q_CORE_EXPORT QByteArray
^
main.cpp:18:30: error: 'QByteArray' is a private member of 'QByteArray'
Container2::Container2(const QByteArray &ba):Container1(ba){}
^
main.cpp:3:18: note: constrained by private inheritance here
class Container1:private QByteArray
^~~~~~~~~~~~~~~~~~
../edge-clang/qt5/include/QtCore/qbytearray.h:167:21: note: member is declared here
class Q_CORE_EXPORT QByteArray
^
I don't understand why this is not allowed for Container2 to inherit Container1 and initialize it through a public constructor, even though the inheritance of QByteArray is private.
#include <QByteArray>
class Container1:private QByteArray
{
public:
Container1() {}
Container1(const QByteArray &ba);
};
Container1::Container1(const QByteArray &ba):QByteArray(ba){}
class Container2:public Container1
{
public:
Container2() {}
Container2(const QByteArray &ba);
};
Container2::Container2(const QByteArray &ba):Container1(ba){}
int main(int argc,char *argv[])
{
QByteArray ba;
Container1 c1(ba);
Container2 c2(ba);
}
Upvotes: 33
Views: 1556
Reputation: 385174
This is a great bug!
In the context of C
, "A
" means "the injected-class-name A
that I get from my base".
You could think of it as C::B::A
.
Of course, that base is inaccessible due to private inheritance:
class A {};
class B : private A {
public:
B() {}
B(const A&) {}
};
class C : public B {
public:
C(const A&) {}
};
int main()
{
A a;
B b(a);
C c(a);
}
// main.cpp:11:13: error: 'class A A::A' is inaccessible within this context
// C(const A&) {}
// ^
// main.cpp:1:9: note: declared here
// class A {};
// ^
You can fix this by calling it ::A
, taking a more indirect route to actually name the exact same type:
class A {};
class B : private A {
public:
B() {}
B(const A&) {}
};
class C : public B {
public:
C(const ::A&) {}
};
int main()
{
A a;
B b(a);
C c(a);
}
// OK
As an aside, the exact same logic applies to private
ly inherited member variables:
int x = 1;
class A
{
private:
int x = 2;
};
class B : A {
public:
B() { int y = x; }
};
int main()
{
A a;
B b(a);
}
// main.cpp: In constructor 'B::B()':
// main.cpp:11:17: error: 'int A::x' is private within this context
// B() { int y = x; }
It all does seem pretty stupid on the face of it, but there's probably a good reason.
In your case, then:
Container2(const ::QByteArray &ba);
Upvotes: 38