21

我的基类如下:

class point    //concrete class
{
 ...    //implementation
}

class subpoint : public point  //concrete class
{
...     //implementation
}

如何从点对象转换为子点对象?我已经尝试了以下所有三种方法:

point a;
subpoint* b = dynamic_cast<subpoint*>(&a);
subpoint* b = (subpoint*)a;
subpoint b = (subpoint)a;

这些演员阵容有什么问题?

4

7 回答 7

38

如何从点对象转换为子点对象?

你不能;除非要么point有一个转换运算符,要么subpoint有一个转换构造函数,在这种情况下,对象类型可以在不需要强制转换的情况下进行转换。

如果引用的对象实际上是 type ,则可以从point 引用(或指针)转换为subpoint 引用subpoint(或指针) :

subpoint s;

point & a = s;
subpoint & b1 = static_cast<subpoint&>(a);
subpoint & b2 = dynamic_cast<subpoint&>(a);

第一个 ( static_cast) 更危险;没有检查转换是否有效,因此如果a不引用 a subpoint,则 usingb1将具有未定义的行为。

第二个 ( dynamic_cast) 更安全,但只有在point多态时才有效(即,如果它具有虚函数)。如果a引用了不兼容类型的对象,则会抛出异常。

于 2012-08-07T22:51:00.907 回答
8

动态转换的目的是“在运行时检查对象是否属于层次结构中的某种类型”。所以现在让我们看看你有什么:

  1. 你有一个点对象。不是子点。
  2. 如果对象是子点,您正在询问动态转换。它不是。
  3. 因为它不是子点,所以 dynamic_cast 失败 - 它告诉您该对象不是您尝试将其转换为的类型。

相比之下,这会奏效:

subpoint c;
point *a = &c;
subpoint* b = dynamic_cast<subpoint*>(&a);
subpoint* b = (subpoint*)a;
于 2012-08-08T03:15:11.350 回答
4

总的来说,这是行不通的,因为point不是subpoint; 只有反过来才是正确的。但是,还有其他问题。

为了:


subpoint* b = dynamic_cast<subpoint*>(&a);

dynamic_cast仅适用于多态类型,即声明至少一个虚函数的类型。我的猜测是它point没有虚函数,这意味着它不能与dynamic_cast.


subpoint* b = (subpoint*)a;

要使此强制转换起作用,point需要将转换运算符声明为subpoint *,例如point::operator subpoint *()


subpoint b = (subpoint)a;

要使此强制转换起作用,point 需要声明一个转换运算符 tosubpoint subpoint需要一个构造函数,该构造函数接受可从 转换的参数point

于 2012-08-07T22:36:51.730 回答
4

对于第一个示例,dynamic_cast仅当基类中至少有一个虚拟方法时才有效。如果对象实际上不是您要转换的类型,它将导致 NULL。

对于第二个示例,您需要&a代替a,但是一旦您修复了该问题,您将获得未定义的行为,因为对象类型错误。

第三个示例需要一个operator subpoint()方法 inpoint在创建副本时进行转换。

于 2012-08-07T22:38:39.467 回答
1

a不能做成一个subpoint。该实施不存在。

于 2012-08-07T22:28:53.663 回答
1

这些演员阵容有什么问题?

您尝试执行它们的事实。Apoint不是 a subpoint,如果它有效,我会感到惊讶。

于 2012-08-07T22:28:58.603 回答
0

我知道这是一个老问题(近十年前),但我最近遇到了同样的问题。

我不确定原始发帖人的意图是什么,但在某些情况下,您可能希望拥有一个从中派生子类的基类,而这些子类仅提供行为不同的方法,并使用相同的基类数据,而不添加任何自己的数据元素。

如果您需要这样做(出于某种原因),并且希望能够将基/父对象向下转换为最初被实例化为父对象的子对象,那么您不想使用虚拟方法,因为它们会起作用你,你将永远被迫使用被实例化的类的虚方法,并且没有多少转换会调用子方法。

So, this can certainly be done. It's just not considered to be "safe". Also, you cannot use dynamic_cast here, it must be a static_cast.

于 2022-01-14T01:44:18.807 回答