为什么派生类不能通过指向base的指针访问其基类的受保护成员?

时间:2016-08-02 10:04:46

标签: c++ inheritance scope protected

这是code

class TestA
{
protected:
    int test=12;

public:
    TestA() {
        cout << "test a: " << test << endl;
    }
    ~TestA() {
    }
};

class TestB : public TestA
{   
public:
    TestB(TestA *testA) {
        cout << "test b: " << testA->test;
    }
    ~TestB() {
    }
};

int main ()
{
    TestA *pTestA=new TestA();
    TestB *pTestB=new TestB(pTestA);
}

我正在尝试使用指向protected类型对象的指针(因此,TestA的实例)访问TestA成员。 TestB也来自TestA

为什么我无法访问它?它只能在我需要它的类中“访问”吗?不在外面使用指针/直接声明?

2 个答案:

答案 0 :(得分:7)

当公共从基类继承时,其受保护的成员变为派生类&#39; 保护成员,这些成员可以在派生类中访问&#39;成员职能。但它们只能通过派生类本身(及其派生类)访问,不能通过基类访问。因此,您无法通过test的指针访问成员TestA,但可以通过TestB的指针访问该成员。

该标准为此提供了一些说明性样本。 $11.4/1 Protected member access [class.protected]

(仅保留示例代码的一部分)

  

除了前面条款中描述的那些之外的附加访问检查   [class.access]在非静态数据成员或非静态时应用   member function是其命名类的受保护成员   ([class.access.base])114如前所述,访问受保护的   成员被授予,因为引用发生在朋友或成员中   某些类C的。如果访问是形成指向成员的指针   ([expr.unary.op]),嵌套名称说明符应表示C或类   从C派生。所有其他访问涉及(可能是隐含的)   对象表达式([expr.ref])。在这种情况下,对象的类   表达式应为C或从C派生的类。[例如:

class B {
protected:
  int i;
};

class D1 : public B {
};

class D2 : public B {
  void mem(B*,D1*);
};

void D2::mem(B* pb, D1* p1) {
  pb->i = 1;                    // ill-formed
  p1->i = 2;                    // ill-formed
  i = 3;                        // OK (access through this)
  B::i = 4;                     // OK (access through this, qualification ignored)
}
     

- 结束示例]

我不确定您的设计意图,使TestB的{​​{1}}朋友成为一个直接的解决方案。

答案 1 :(得分:0)

WORLD的集体成员可访问性概念适用于此处。 WORLD只能访问类的公共成员,无论它们是如何创建/派生的。

考虑以下示例:

class A
{
    public:
        int public_i;
    protected:
        int protected_i;
    private:
        int private_i;

    public:
        A()
        {
            public_i = 10;
            protected_i = 20;
            private_i = 30;
        }
};

class C : protected A
{
    public:
        void Access(void)
        {
            cout << public_i << endl;
            cout << protected_i << endl;
            //cout << private_i << endl; // <- Not Allowed b'coz its private here
        }
};
class D : private A
{
    public:
        void Access(void)
        {
            cout << public_i << endl;
            cout << protected_i << endl;
            //cout << private_i << endl; // <- Not Allowed b'coz its private here
        }
};
class B : public A
{
    public:
        void Access(D *pd)
        {
            cout << public_i << endl;
            cout << protected_i << endl;
            //cout << private_i << endl; // <- Not Allowed b'coz its private here

            //pd is WORLD here
            //cout << pd->public_i << endl;    // <- Not Allowed b'coz its private here since private inheritance of A by D
            //cout << pd->protected_i << endl; // <- Not Allowed b'coz its protected here
            //cout << pd->private_i << endl; // <- Not Allowed b'coz its private here
        }
};


int main ()
{
    A objA;
    cout << objA.public_i << endl;
    //cout << objA.protected_i << endl; // <- Not Allowed b'coz its protected here
    //cout << objA.private_i << endl;   // <- Not Allowed b'coz its private here

    B objB;
    cout << objB.public_i << endl;
    //cout << objB.protected_i << endl; // <- Not Allowed b'coz its protected here
    //cout << objB.private_i << endl;   // <- Not Allowed b'coz its private here

    C objC;
    //cout << objC.public_i << endl;    // <- Not Allowed b'coz its protected here
    //cout << objC.protected_i << endl; // <- Not Allowed b'coz its protected here
    //cout << objC.private_i << endl;   // <- Not Allowed b'coz its private here

    D objD;
    //cout << objD.public_i << endl;    // <- Not Allowed b'coz its private here
    //cout << objD.protected_i << endl; // <- Not Allowed b'coz its protected here
    //cout << objD.private_i << endl;   // <- Not Allowed b'coz its private here

    //Outside class its all WORLD and WORLD can access only public members.
    //Objects and Pointers are WORLD.

    //Same thing is applicable when class members are accessed via pointers.
    B *pobjB;       //pobjB is WORLD
    cout << pobjB->public_i << endl;
    //cout << pobjB->protected_i << endl; // <- Not Allowed b'coz its protected here
    //cout << pobjB->private_i << endl;   // <- Not Allowed b'coz its private here

    objB.Access(&objD);
    objC.Access();
    objD.Access();

    return 0;
}