【发布时间】:2015-05-04 20:40:54
【问题描述】:
我的 C++ 程序中有 2 个对象,它们都从同一个父类扩展而来: A 类和 B 类,都扩展了类基础。
是否可以使用 A 类创建一个对象,然后在程序中将其更改为 B 类?
【问题讨论】:
-
原则上,这不是一个好主意。你能解释一下你为什么需要它以及你打算如何使用它吗?
-
写一个转换函数,可以将
class A的对象转换为class B的对象。
我的 C++ 程序中有 2 个对象,它们都从同一个父类扩展而来: A 类和 B 类,都扩展了类基础。
是否可以使用 A 类创建一个对象,然后在程序中将其更改为 B 类?
【问题讨论】:
class A的对象转换为class B的对象。
简短的回答,不。您不能安全地从 A 转换为 B 或 B 到 A。您可以安全地转换为基类,因为 A IS_A 基类和 B IS_A 基类,但 A 而不是 B,反之亦然。没有便携式或安全的方法可以做到这一点。虽然您的编译器可能允许您这样做,并且它可能看起来有效,但以这种方式在不相关的类之间进行转换的结果是未定义的。
顺便说一句,没有理由不能添加强制转换构造函数来允许从 B 构造 A,反之亦然。那将是完全安全的。您只需使用 A 的成员来初始化 B 的成员,反之亦然。您必须处理的任何不常见的成员都可能会为其分配默认值。
【讨论】:
class A 创建一个函数(或者,如果您愿意,可以创建一个重载的构造函数...),它接受class B 的实例作为其输入并填充 (@987654323 @) 对象使用取自它的值。这不仅“工作得很好”,而且也清楚地表明程序有时需要这样做。您不是“将一个类转换为另一个类”,而是“基于从一个(特定)其他类的实例中获取的(特定)值来初始化一个类的对象的实例”。而且,您明确说明了如何做到这一点。
以下代码有效:
#include <iostream>
class Base {};
struct A : public Base {int a;};
struct B : public Base {int b;};
int main()
{
A *a = new A();
a->a = 1;
B *b = reinterpret_cast<B *>(a);
std::cout << b->b << std::endl;
return 0;
}
这非常难看,如果A 和B 没有完全相同的内存布局,它将无法正常工作。如果您需要 a 和 b 成为同一个对象,则此方法有效。如果您不介意它们是不同的对象并且驻留在内存中的不同位置,那么您可以在B 中编写一个构造函数,接收A 类型的对象或转换运算符。
这听起来像是 XY Problem 的经典示例,并且可能存在更优雅的解决方案来解决您的实际问题。
正如其他人所提到的,不,你不能这样做......从技术上讲。你其实可以通过转换构造函数和虚函数来达到这个效果。
如果你写了一个从 A 到 B 和 B 到 A 的转换构造函数:
A::A(B convertFrom); // Convert from B to A
B::B(A convertFrom); // Convert from A to B
并且您将每个类的基本部分设为虚拟:
class base
{
virutal void baseClassFunction();
};
class A
{
virtual void baseClassFunction()
{
// Do things for A
}
};
Class B
{
virtual void baseClassFunction()
{
// Do things for B
}
}
然后您可以简单地创建一个base 类型的指针,它可以保存对A 或B 的引用。
将所有内容组合在一起的示例;
int main()
{
base *ptr = new A();
bool needs_to_be_B;
...
// Program logic
ptr->baseClassFunction();
...
if(needs_to_be_B)
{
base *tmp = new B(*ptr);
delete ptr;
ptr = tmp;
delete tmp;
}
// ptr is now a B
ptr->baseClassFunction();
}
如果您感到困惑,请查找虚函数并转换构造函数。
【讨论】: