受保护成员访问只有在没有得到其地址时才有效

Protected member access works only when not getting its address

本文关键字:地址 有效 访问 成员 受保护      更新时间:2023-10-16

我有多重继承(类A是基类,BA派生,CB派生)。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 error message:

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.

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

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

参考:c++ 14,5.3.1/3

如果操作数是限定id,命名某个类型为T的类C的非静态成员m,则结果的类型为"指向类型为T的类C成员的指针",并且是指定C::m的右值

由于Precursor::x不是类的静态成员,因此无法获取其地址。您需要声明实例,并获取实例的地址成员。这就是为什么这个->x工作:1. C继承B,它有从B继承的元素x和2.