2009-09-24 83 views
9

是否有可能摆脱error C2243摆脱错误C2243

class B {}; 
class D : protected B {}; 

D d; 
B *p = &d; // conversion from 'D *' to 'B &' exists, but is inaccessible 

我在我的应用程序有这个错误,并在结束时,我已经成功通过进行显式转换编译它:为什么通过使d类继承保护

D d; 
B *p = (B*)&d; 

我无法理解从B使隐式转换无法访问。

我试图以进行转换访问创造d一流的运营商B(),以避免显式转换:

class B {}; 
class D : protected B 
{ 
public: 
operator B() {return *this;} 
}; 

但也没有办法。

任何其他解决方案,以避免显式转换?

回答

17

如果你想允许转换,你应该使用公共继承。

使用受保护或私有继承,您声明派生类型从基类继承的事实是一个不应该从外部可见的细节:这就是为什么你会得到该错误。

您应该将非公开继承仅限于作为一种组合形式,并有可能覆盖方法。

+0

什么基类的const接口?所以私下继承并允许投射到const base&?因为无法让它在MSVC上工作... – 2017-04-07 17:49:04

+0

只需回复自己,您需要通过聚合而不是继承来处理类,否则MSVC会感到困惑并尝试通过私有继承来解决转换(隐藏投射运算符) – 2017-04-07 17:54:35

8

因为protectedprivate继承不是is-a的关系,它们只是语法糖的组成。你的类可以改写正是这样,但你失去让编译器的方便定义b你,并采用B的成员,而不是直接引用它明确:

class D 
{ 
    protected: 
    B b; 
}; 

对于第二点你的问题:

operator B() {return *this;} 

这条线与BD做。 D *和B *与B和D完全不同,尽管它们是指向它们的指针!投三分球,你可以重新解释指针:

B *p = reinterpret_cast<B*>(&d); // TOTALLY WRONG, although it compiles :) 

不要做上面的线!我想你可能会给我们更多关于你想要达到的信息。

2

因为出于D和Ds的孩子,没有人知道他们是父母孩子,所以你需要明确地做。

那是什么保护继承意味着,只有你的家人(孩子)会知道你继承。你可以使用它,例如在儿童方法中,隐式转换将是合法的。

如果你想隐式转换你的孩子,你需要公开给每个人知道。

0

您是否尝试在D类中公开操作符B()?在你显示的代码中,它将被标记为受保护的并且仍然无法访问。但如果可能的话,我会尽量避免转换操作符。

尽管如此,继承保护B意味着你打算阻止做B * p = & d。想象一下,如果B实际上是D的顶部受保护的成员变量。就像在这种情况下不能访问D.b一样,除非抛弃它,否则不能访问d作为B *。

所以要么公开继承B,要么使用你的强制转换。我会公继承地继承B,因为继承它的基本保护措施是“不要用我作为B”,无论如何你都试图去做。

+1

使运算符B ()public也不起作用 – 2009-09-24 13:58:36

2

这里的问题是,您正在尝试围绕保护属性提供的信息隐藏信息。如果你想访问D的一个实例作为B,为什么你将它继承为protected而不是public ?.你在使用受保护的继承时说的是,你只希望D及其后代的实例知道B组件。你需要再看看你想完成什么。

您使用的旧C风格转换没有新的C++转换的微妙之处,因此它会为您提供将编译的代码,但问题确实存在于继承中。

0

由于外无人知道他们是父子,你只能执行D的衍生class.This这个动作的例子(测试在Visual Studio 2013):

大约只给访问
class BASE{}; 

class BASE1 :protected BASE{}; 

class BASE2 :protected BASE1 
{ 
public: 
    void func(BASE &a, BASE1 &b){a = b;} 
}; 

void main() 
{ 
    BASE a; 
    BASE1 b; 
    BASE2 c; 

    c.func(a, b);; 
    system("pause"); 
}