摆脱错误C2243

时间:2009-09-24 13:46:37

标签: c++ inheritance casting implicit-cast

是否有可能摆脱error C2243

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

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

我在我的应用中遇到此错误,最后我设法通过显式转换来编译它:

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

我无法理解为什么通过使D类继承受B保护而使得隐式转换不可访问。

我尝试通过在D类中创建运算符B()来避免显式转换,以便可以进行转换:

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

但是没有办法。

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

6 个答案:

答案 0 :(得分:17)

如果要允许转换,则应使用公共继承。

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

您应该将非公共继承视为一种组合形式,并且可以覆盖方法。

答案 1 :(得分: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 :(得分:2)

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

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

如果你想让你的孩子隐性转换,你需要公开让所有人知道。

答案 3 :(得分:2)

这里的问题是您正试图绕过受保护的属性提供的隐藏信息。如果要将D的实例作为B访问,为什么要将其作为受保护而不是公共继承?您在使用受保护的继承时所说的是您只希望D及其后代的实例知道B组件。您需要再次查看要完成的任务。

您正在使用的旧C样式转换没有新的C ++转换的精妙之处,因此它为您提供了将编译的代码,但问题实际上在继承中。

答案 4 :(得分:0)

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

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

所以要么公开地继承B,要么使用你的演员表。我继续公开继承B,因为继承它保护基本上说“不要用我作为B”,无论如何你都试图做。

答案 5 :(得分:0)

因为外面没有人知道他们是亲子,所以你只能在D的派生类中执行这个动作。这是一个例子(在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");
 }