从子类访问私有继承类的名称

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

本文关键字:继承 子类 访问      更新时间:2023-10-16

以下代码在 g++ 中编译失败,使用 g++ 时出现此错误,使用 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
                    ^

我不明白为什么不允许 Container2 继承 Container1 并通过公共构造函数初始化它,即使 QByteArray 的继承是私有的。

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

这是一个很棒的错误!

C语境中,"A"的意思是"我从我的基地得到的注入的类名A"。
你可以把它想象成C::B::A.
当然,由于私有继承,该基础无法访问:

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

(现场演示)

您可以通过将其称为 ::A 来解决此问题,采用更间接的路线来实际命名完全相同的类型:

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

(现场演示)


顺便说一句,完全相同的逻辑适用于private继承的成员变量:

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

(现场演示)

从表面上看,这一切看起来确实很愚蠢,但可能有一个很好的理由。


在您的情况下,那么:

Container2(const ::QByteArray &ba);