Yur*_*ash 6 c++ inheritance compiler-errors protected
首先,我了解C++标准(ISO/IEC 14882:2003):第11.5节,第1段,这不是那种情况(但是compliler显然不这么认为).
我尝试通过这个指针在派生类方法中调用受保护的基类方法,静态转换为基类指针并在MSVC2008中出现错误C2248:'A :: f':无法访问在类'A'中声明的受保护成员.
我必须在"奇怪的重复模板模式"的上下文中执行此操作,但我可以在更简单的代码中重现此错误,如下所示:
class B
{
protected:
void f(){}
};
class D : public B
{
public:
void g()
{
f(); // ok
this->f(); // ok
static_cast<B*>(this)->f(); // C2248 in MSVC2008
dynamic_cast<B*>(this)->f(); // C2248
((B*)this)->f(); // C2248
}
};
D d; d.g();
Run Code Online (Sandbox Code Playgroud)
似乎编译器认为将此指针作为指向其他实例的指针,是吗?
在这种情况下编译器是错误的,你怎么看?
好的,我的真实代码更像是:
template<class T>
class B
{
public:
void g()
{
f(); // error C3861: 'f': identifier not found
this->f(); // error C3861: 'f': identifier not found
// static_cast to derived class
static_cast<T*>(this)->f(); // C2248 in MSVC2008
}
};
class D : public B<D>
{
protected:
void f(){}
};
Run Code Online (Sandbox Code Playgroud)
我把它转换为派生类,我不能使用this-> f();
顺便说一下,我看到这段代码对于使用不安全,例如class E : public B<D> {...};:compilable,但static_cast会导致错误的强制转换.
eca*_*mur 13
编译器是正确的.要显式访问B::f成员函数,您可以编写:
this->B::f();
Run Code Online (Sandbox Code Playgroud)
相关语言是:
11.4受保护的成员访问[class.protected]
[...]授予对受保护成员的访问权限,因为引用发生在朋友或某个C类成员中.[...]访问受保护成员[...]涉及[可能是隐含的]对象表达式(5.2.5).在这种情况下,对象表达式的类应为C或从C派生的类.
因此,通过强制转换为基类的受保护成员访问B违反了此授权,并且是不允许的.您也可以使用this->B::f()上述原因.
在你的实际CRTP动机的情况下,你是正确的,你不能f()没有a static_cast,因为D它不是一个基类B<D>(继承关系在另一个方向).由于D不是基类B<D>,因此无论如何都无法调用其protected方法B<D>.一个简单的解决方法是friend B<D>,以D和使用static_cast上的this指针:
template<typename T>
class B {
public:
void g() {
static_cast<T *>(this)->f();
}
};
class D : public B<D>
{
friend class B<D>;
...
Run Code Online (Sandbox Code Playgroud)
如果允许B访问您担心的private部分D,您可以将private部件移动到另一个基类并隔离CRTP机制D:
template<class T> class B {
public:
void g() {
static_cast<T*>(this)->f();
}
};
class C {
private:
void h();
protected:
void f(){ std::cout << "D::f\n"; }
};
class D: protected C, public B<D>
{
friend class B<D>;
};
Run Code Online (Sandbox Code Playgroud)
这里B<D>是从防止调用C::h友谊既不继承,也不传递.