Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing the name of a private-inherited class from a subclass

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); } 
like image 239
user2923436 Avatar asked Jan 11 '17 15:01

user2923436


People also ask

How do you access private members of inherited classes?

Private members of a base class can only be accessed by base member functions (not derived classes). So you have no rights not even a chance to do so :) Show activity on this post. Well, if you have access to base class, you can declare class B as friend class.

Can private be accessed by subclass?

A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass. A nested class has access to all the private members of its enclosing class—both fields and methods.


1 Answers

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 {}; //        ^ 

(live demo)

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 

(live demo)


As an aside, the exact same logic applies to privately 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; } 

(live demo)

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); 
like image 195
Lightness Races in Orbit Avatar answered Oct 01 '22 13:10

Lightness Races in Orbit