从子类访问私有继承类的名称 [英] Accessing the name of a private-inherited class from a subclass

查看:72
本文介绍了从子类访问私有继承类的名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码无法使用g ++编译此错误以及与clang类似的错误。

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
                    ^

我不明白为什么Container2不允许继承Container1并通过公共构造函数初始化它,即使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);
}


推荐答案

这是一个很棒的错误!

This is a great bug!

C 的上下文中, A 是指从我的基地获得的注入类名 A

您可以将其视为 C :: B :: A

当然,由于私有继承,该基地无法访问:

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



实时演示



你可以通过调用它来解决这个问题 :: 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



实际演示






顺便说一句,完全相同的逻辑适用于 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; }



现场演示



从表面看来这一切看起来都很愚蠢,但这可能是一个很好的理由。

(live demo)

It all does seem pretty stupid on the face of it, but there's probably a good reason.

在您的情况下,然后:

Container2(const ::QByteArray &ba);

这篇关于从子类访问私有继承类的名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆