【问题标题】:Transforming a base class into one of its derived classes?将基类转换为其派生类之一?
【发布时间】:2011-11-12 08:37:58
【问题描述】:

有没有捷径可以将基类转换为程序内部的派生类之一?例如:

假设我有三个类,一个基类和两个派生类:

class cColor {
};

class cBlue : public cColor {
};

class cRed : public cColor {
};

然后我在我的程序中创建一个 Color 类:

int main(){
cColor unsaturated
return 0;
}

有没有办法将unsaturated 从 cColor 类转换为 cBlue 或 cRed 类?类似的解决方案是将unsaturated 存储在指针中,从指针创建新的cBlue 或cRed 类,然后删除unsaturated

【问题讨论】:

  • 你心目中的“转型”是什么意思?答案是“不”,但我完全相信你没有以正确的方式思考你的问题,而且你实际上不会想要任何这样的事情。
  • @Kerrek SB 好吧,我想在我的程序中实现一个基础对象,但让它能够根据用户输入动态更改。使用简单的类确实没有什么区别,但我相信在处理广泛和/或详细的类时会成为一个问题
  • 在 C++ 中不可能有这样的事情。一个对象活着,然后它就死了。它始终是一种固定类型。没有“变异类型”这样的东西。但是,这不是必需的:通常您首先确定您想要什么样的对象,然后创建正确的对象。在构造对象之前,您可以拥有一个保存相关信息的中间调度程序项,但无需“覆盖”现有对象。
  • @KerrekSB 感谢您的帮助,我可以想出不同的方法来实现我所要求的,但真正的问题是是否有预定义的、更简单的处理方法。显然,每个人都告诉我,改变一个对象可能是灾难性的或危险的,所以这就回答了我的问题。感谢您尝试深入研究:P

标签: c++ class inheritance


【解决方案1】:

创建对象后无法更改其类型(构造和销毁除外,派生类对象临时变为基类对象)。由于派生类对象可能比它们的基类大,所以这也是不可能的。

如果没有其他人持有另一个指向基类的指针,则创建新派生对象、重置指针然后销毁基对象的解决方法有效。如果有任何其他指向原始对象的指针或引用,之后它将悬空。但是,如果你控制着对类的唯一指针/引用(例如,如果你只通过一个从不泄漏指针或对真实对象的引用的单例代理对象来访问它),那么这个方法就可以工作。

【讨论】:

  • 好的,感谢您回答我的问题。感谢您的宝贵时间。
  • 我不同意“这也无法正常工作”,因为如果标准更改为允许您(即使使用手动内存管理),也可以在 c++ 中实现。编译器需要做的就是为尽可能大的实例分配空间:)zzz。 +1。
  • @trinithis:编译器应该如何知道最大可能实例的大小(可能在另一个翻译单元中定义,在编译这个时尚未编写) ?
  • @trinithis:动态库呢?
【解决方案2】:

我对 C++ 有点生疏,但我相信你是对的。如果要将变量声明为 cColor,并为其分配 cBlue 或 cRed 实例,则需要使用指针。

cColor* unsaturated = new cBlue();

【讨论】:

  • 您也可以使用引用 - 但必须始终对其进行初始化。 c红色红色; cColor &ref=red;
  • 这是我的预期,但是,我仍然想知道是否有一种方法可以专门将基类转换/变异/变形为派生类,而无需创建派生类的新实例
【解决方案3】:

你可以做一个 reinterpret_cast,但是,从一个基类到另一个类是非常不安全的,因为源类中不存在的目标类的数据成员不会被初始化为任何东西。

通常您可以使用复制构造函数来解决这种情况。比如……

class cColor 
{ 
   cColor( ColorData );
   ColorData getData();
}; 

class cBlue : public cColor { 
}; 

class cRed : public cColor { 
}; 

那么……

int main(){     
ColorData foo;
cColor unsaturated(foo);
rColor rcol(unsaturated.GetData());
return 0;     
}   

【讨论】:

  • 感谢您的回答。不过,我并不是在寻找一种“绕过”的方法,我只是想知道是否有方法,从我收到的回复来看,没有。
【解决方案4】:

您想要的是使用 GoF 第 305 页中的状态模式,您提出的是将基对象的实例强制转换为派生类而不是派生类是非常危险的。诚然,您可能会摆脱简单的示例,但是一旦派生类添加一些状态或更改 vtable,它就会崩溃。 http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/ref=sr_1_1?s=books&ie=UTF8&qid=1321058151&sr=1-1

【讨论】:

    猜你喜欢
    • 2017-01-08
    • 2013-11-17
    • 2012-12-06
    • 2021-02-18
    • 2017-07-18
    • 2011-02-04
    • 2012-09-15
    相关资源
    最近更新 更多