30 votes

Accès au nom d'une classe à héritage privé à partir d'une sous-classe

Le code suivant ne se compile pas avec cette erreur avec g++ et une erreur similaire avec 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
                    ^

Je ne comprends pas pourquoi il n'est pas permis à Container2 d'hériter de Container1 et de l'initialiser par un constructeur public, même si l'héritage de QByteArray est privé.

#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);
}

36voto

C'est un super bug !

Dans le cadre de C , " A " signifie " le nom de classe injecté A que je reçois de ma base".
On peut le voir comme C::B::A .
Bien sûr, cette base est inaccessible en raison de l'héritage privé :

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

( Démonstration en direct )

Vous pouvez corriger cela en l'appelant ::A en prenant un chemin plus indirect pour nommer exactement le même 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

( Démonstration en direct )


Soit dit en passant, la même logique s'applique à private ly les variables membres héritées :

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; }

( Démonstration en direct )

Tout cela semble assez stupide à première vue, mais il y a probablement une bonne raison.


Dans votre cas, alors :

Container2(const ::QByteArray &ba);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X