受保护的成员访问仅在未获取其地址时起作用

时间:2016-07-01 08:29:40

标签: c++ inheritance

我有多重继承(类A是基类,B派生自AC派生自B)。 A有一个受保护的成员属性,我尝试在C中以不同的方式访问该属性。

考虑以下代码:

#include <iostream>
using namespace std;

class A {
protected:
        int x;
public:
        A() : x(42) {}
};

class B : public A {
};

class C : public B {
protected:
        typedef B Precursor;

public:
        void foo() {
                cout << Precursor::x << endl;
                cout << this->x << endl;
        }

        int get() {
                return Precursor::x;
        }

        int* getPtr() {
                // error: ‘int A::x’ is protected
                // error: within this context
                // error: cannot convert ‘int A::*’ to ‘int*’ in return
                return &Precursor::x;
                //return &this->x;  // this works
        }
};


int main() {
        C obj;
        obj.foo();
        cout << obj.get() << endl;
        cout << obj.getPtr() << endl;
}

C::foo()C::get()中,Precursor::x可以访问x。 但是,&Precursor::x不起作用。这是为什么? this->x&this->x始终有效。

Clang错误消息:

cpp-inheritance.cpp:34:22: error: 'x' is a protected member of 'A'
                return &Precursor::x;
                                   ^
cpp-inheritance.cpp:7:6: note: must name member using the type of the current context 'C'
        int x;
            ^
cpp-inheritance.cpp:34:10: error: cannot initialize return object of type 'int *' with an
      rvalue of type 'int A::*'
                return &Precursor::x;
                       ^~~~~~~~~~~~~
2 errors generated.

2 个答案:

答案 0 :(得分:4)

如果&运算符用于C::m表单的限定名称,其中C是一个类而m是非静态成员,则返回指向C::*T类型的成员指针,其中Tm的类型。这是一种特殊情况,它会覆盖返回指向用作&操作数的表达式的指针的默认行为。

要获取指向C::m的指针,其中C是基类,您必须使其&的操作数不是限定名,例如使用&this->C::m&(C::m)

参考:C ++ 14,5.3.1 / 3

  

如果操作数是一个qualic fi-id,命名一个类型为T的某个类C的非静态成员m,则结果类型为“指向类型为C的C类成员的指针”,并且是一个指定C :: m的prvalue

答案 1 :(得分:0)

因为Precursor :: x不是类的静态成员,所以无法获取其地址。您需要声明实例,并获取实例的地址成员。这就是为什么这个&gt; x有效: 1. C继承B它具有继承自B的成员x 和 2.这指定C的当前实例。