更新1:
更正了无意义的代码!感谢您的评论,我制作了第一个片段的散列,oops。
更新2:
同样更新了问题标题,因为已经指出使用dynamic_cast是不必要的答案。
我在这里想要实现的是使用强类型的深层复制;我希望能够将Class2复制到Class2的另一个实例;但是,我也想使用Class1作为基础的CopyTo函数。这个想法来自我的C#体验,通常我只是将返回类型设为泛型(参见C#片段)。
void Class1::CopyTo(Class1 *c1)
{
// Write data in to c1 from this instance.
c1->exampleData = exampleData;
}
// Class2 inherits Class1
Class2 *Class2::Copy()
{
Class2 *c2a = new Class2();
CopyTo(c2a);
Class2 *c2b = dynamic_cast<Class2*>(c2a);
return c2a;
}
这就是我在C#中的方式:
public class Class1
{
T Copy<T>()
where T : Class1
{
/* Can't remember the best way to do this in C#;
* basically if T was Class2 this would need to create
* a new instance of that class, and the same goes for
* Class1. */
T copy = createNewInstance();
// Copy the data from this to 'copy'.
copy.exampleData = exampleData;
return copy;
}
}
现在,与C#代码段相比,C ++代码段感觉很臭。是否有可能在没有指针的情况下做到这一点,或者这是最佳实践?
答案 0 :(得分:1)
我不清楚你在问什么,但要注意当你说:
Class2 *c2 = dynamic_cast<Class2*>(c1);
强制转换的结果可能为NULL,您必须检查此内容。
答案 1 :(得分:1)
您应该更多地处理代码段。
GetSomethingCopy正在创建一个传递给CopyTo的Class2类型的指针。 CopyTo尝试调用从未初始化的接收指针的成员函数:分段错误,程序死亡。
即使没有杀死应用程序,你也试图将 dynamic_cast 从Class2 *转换为Class2 *,这就是什么都不做。如果您打算从CopyTo转换返回的值,则必须知道不能在void *上使用dynamic_cast。您必须更改CopyTo签名以返回Class1(以便以后可以将其强制转换)或在void *上使用static_cast。
请注意,Copy是Class1中的一个虚函数,实际上是在Class2中执行的,并且创建了一个Class2对象,否则返回的元素将不是Class2,而是Class1。
CopyTo方法的名称令人困惑,因为它不是将复制到参数而是复制参数。
毕竟,我仍然不知道你在问什么。你想在哪里使用堆栈内存?您可以将堆栈分配的元素传递给函数,但是返回指向堆栈分配元素的指针/引用也是一个分段错误:当函数结束并且接收器将留下悬空指针/引用时,对象将被销毁。
现在,如果你的问题更能理解你是否可以在堆栈分配元素上使用dynamic_cast,那么你可以(假设Class2继承自Class1):
void f()
{
Class2 c2;
Class1 &c1 = c2; // c1 is a Class1 reference to a Class2 object
dynamic_cast<Class2&>(c1).class2method();
// or:
dynamic_cast<Class2*>(&c1)->class2method();
}
如果您更新代码,请在此回答中发表评论,以便我注意到并可以在今晚更正。
答案 2 :(得分:0)
该代码没有任何意义如上所述......无论如何我“猜测”如果你没有使用void *作为回报,你可以使用静态转换吗?
好了,现在代码是有道理的。
您不需要任何动态强制转换,它已经是Class2类型。
答案 3 :(得分:0)
在CopyTo函数中,您将返回指向在堆栈上创建的对象的指针 - 这是不可能的,因为当函数返回时,指针指向的对象将被销毁。
在回答您的问题时,您可以在指针或引用上使用dynamic_cast
。在您的情况下,我可能使用new
而不是堆栈分配要动态返回的对象,然后您可以安全地返回指针。但是,我倾向于使用dynamic_cast
作为潜在的代码气味,以及应该使用虚函数的标志。
答案 4 :(得分:0)
不,dynamic_cast仅适用于指针和引用。无论如何你都无法安全地返回你在堆栈上分配的任何东西,所以在这种情况下我不确定你打算如何修改你的代码。
答案 5 :(得分:0)
我不确定你想要实现什么,因为代码仍然没有多大意义。但是,我认为以下内容应该与您正在尝试的内容相近。请注意,我不使用堆内存:它不是必需的,它会泄漏内存。
template <typename T>
T Class1::Copy()
{
T instance;
CopyTo(&instance);
return instance;
}
这是有效的,因为您将instance
的(多态)指针传递给CopyTo
的{{1}}方法。
然后你可以像这样调用代码:
Class1
然而,这段代码仍然气味,因为它不是惯用的C ++:在C ++中,你通常会编写一个复制构造函数。后期绑定Class2 x1;
// Fill x1
Class2 x2 = x1.Copy<Class2>();
方法确实存在,但它们很少需要,并且上面不是后期绑定(但是你的C#代码也没有)。
答案 6 :(得分:0)
void Class1::CopyTo(Class1& c1)
{
// Write data in to c1 from this instance.
c1.SomeIntValue = SomeIntValue;
}
// Class2 inherits Class1
Class2* Class2::Copy()
{
Class2 *c2 = new Class2();
CopyTo(*c2);
return c2;
}
//or more idiomatic
Class2 Class2::Copy()
{
Class2 c2
CopyTo(c2);
return c2;
}