0

更新1:

更正了胡说八道的代码!感谢您的评论,我对第一个片段进行了哈希处理,哎呀。

更新 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++ 片段感觉很臭。是否可以在没有指针的情况下执行此操作,或者这种方式是最佳实践?

4

7 回答 7

1

我不清楚您在问什么,但请注意,当您说:

 Class2 *c2 = dynamic_cast<Class2*>(c1);

强制转换的结果可能为 NULL,您必须对此进行检查。

于 2009-04-09T09:47:26.760 回答
1

您应该在代码片段上多做一些工作。 GetSomethingCopy 正在创建一个 Class2 类型的指针,该指针被传递给 CopyTo。CopyTo 尝试调用从未初始化的接收指针的成员函数:分段错误并且程序死亡。

即使这没有杀死应用程序,您也正在尝试从 Class2* 到 Class2* 的dynamic_cast,这几乎什么都不做。如果您打算从 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();
}

如果您更新代码,请在此答案中发表评论,以便我注意到并在今晚更正它。

于 2009-04-09T10:31:43.393 回答
0

如前所述,该代码没有任何意义……无论如何,如果您不使用 void* 作为 return ,我“猜想”您可以使用静态强制转换?

好的,现在代码有意义了。

您不需要任何动态转换,它已经属于 Class2 类型。

于 2009-04-09T09:46:30.007 回答
0

在您的 CopyTo 函数中,您将返回一个指向在堆栈上创建的对象的指针 - 这是不可能的,因为指针指向的对象将在函数返回时被销毁。

在回答您的问题时,您可以使用dynamic_cast指针或引用。new在您的情况下,我可能会使用而不是在堆栈上分配要动态返回的对象,然后您可以安全地返回一个指针。但是,我倾向于将 usingdynamic_cast视为潜在的代码异味,以及应该使用虚函数的标志。

于 2009-04-09T09:48:09.550 回答
0

不,dynamic_cast 仅适用于指针和引用。无论如何,您都无法安全地返回您在堆栈上分配的任何内容,因此我不确定在这种情况下您打算如何修改代码。

于 2009-04-09T09:55:22.980 回答
0

我不确定您要实现什么,因为代码仍然没有多大意义。但是,我相信以下内容应该近似于您正在尝试做的事情。请注意,我使用堆内存:这不是必需的,它会泄漏内存。

template <typename T>
T Class1::Copy()
{
    T instance;
    CopyTo(&instance);
    return instance;
}

这是有效的,因为您将(多态)指针传递instanceCopyTo.Class1

然后你可以这样调用代码:

Class2 x1;
// Fill x1
Class2 x2 = x1.Copy<Class2>();

但是,这段代码仍然有异味,因为它不是惯用的 C++:在 C++ 中,您通常会编写一个复制构造函数。后期绑定的Copy方法确实存在,但它们很少需要,并且上面不是后期绑定的(但您的 C# 代码也不是)。

于 2009-04-09T12:49:35.730 回答
0

啊,现在问题很清楚了。从技术上讲,答案是否定的,不是 dynamic_cast<>,但我真的不明白你为什么想要它。看来你只是想要

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;
}
于 2009-04-09T12:51:01.390 回答