我有一个简单的类层次结构,包含基类和派生类。基类有两个派生类调用的受保护成员。来自最近的一些C#体验,我认为最好让界面更流畅并允许链接方法调用,因此不是调用this->A()
,而是this->B()
,你可以调用{{1} }}。但是,以下代码将无法编译:
this->A()->B()
这会产生以下编译器错误:
#include <iostream>
class Base
{
protected:
Base* A()
{
std::cout << "A called." << std::endl;
return this;
}
Base* B()
{
std::cout << "B called." << std::endl;
return this;
}
};
class Derived : public Base
{
public:
void Test()
{
// Base::A and Base::B are private here.
this->A() // This works fine
->B(); // Suddenly I cannot access my own private method?
}
};
int main()
{
Derived d;
d.Test();
return 0;
}
我也尝试将基类方法设为虚拟,但这没有用。
我的C ++足够生疏,我似乎无法弄清楚这里发生了什么,所以非常感谢帮助。我也想知道这是不是一个坏主意,因为main.cpp: In member function 'void Derived::Test()':
main.cpp:12:15: error: 'Base* Base::B()' is protected
Base* B()
^
main.cpp:26:21: error: within this context
->B(); // Suddenly I cannot access my own private method?
^
和C ++ - 人们不习惯这样流畅的界面。
答案 0 :(得分:8)
类中的受保护成员只能通过派生类从派生类访问,即通过派生类的对象,或引用或指向该派生类。
A()
的返回类型是Base*
,它不是派生类,这就是您无法访问其受保护成员的原因。编译器不会跟踪它是否真正引用同一个对象。
答案 1 :(得分:2)
是的,您无法从Base
调用Base *
类的受保护方法。您可以认为受保护的方法是私有的,区别在于它们也变得属于派生类。
答案 2 :(得分:2)
这是正确的行为,你不能为你只能通过派生类调用的另一个类调用受保护的函数,因为当你调用this->A()
时它会返回一个不同类的Base *。原因是,如果你做了类似的事情,
class Derived : public Base
{
public:
void Test()
{
baseInstance->B(); // this shouldn't be possible. If the case was you can call it through a pointer or an object this would be possible.
}
Base* baseInstance;
};
同样最好指出派生的和this
可能没有相同的地址,它可能有不同的地址。当您实际将Base*
强制转换为Derived*
时,编译器将处理地址的差异,如果像static_cast<Derived*>(this->A())->B();
答案 3 :(得分:2)
要添加到Sebastian,可以通过以下方式解决这个问题,但不是很好:
static_cast<Derived*>(this->A())->B();
答案 4 :(得分:2)
您可以参考标准来获得问题的答案
11.2基类和基类成员的可访问性[class.access.base]
如果
,则可在R处访问N的基类B.
— an invented public member of B would be a public member of N, or
— R occurs in a member or friend of class N, and an invented public member of B would be
a private or
protected member of N, or
— R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or
— there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R
如果您通过Base指针引用该成员,则上述子句均不满足。