C ++继承向下转换

时间:2012-08-07 22:27:26

标签: c++ inheritance casting downcast

我的基类如下:

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;

这些演员有什么问题?

6 个答案:

答案 0 :(得分:25)

  

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

你不能;除非point有转换运算符,或subpoint有转换构造函数,否则转换对象类型时无需转换。

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

subpoint s;

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

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

第二个(dynamic_cast)更安全,但仅在point具有多态性(即,如果它具有虚函数)时才有效。如果a引用了不兼容类型的对象,那么它将引发异常。

答案 1 :(得分:3)

对于第一个示例,dynamic_cast仅在基类中至少有一个虚方法时才有效。如果对象实际上不是您要尝试的类型,则会导致NULL。

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

第三个示例要求operator subpoint()中的point方法在创建副本时进行转换。

答案 2 :(得分:3)

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

  1. 你有一个点对象。不是一个小点。
  2. 如果对象是一个子点,你会问一个动态转换。不是。
  3. 因为它不是一个子点,所以dynamic_cast失败了 - 它告诉你对象不是你试图把它投射到的类型。
  4. 相比之下,这会有效:

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

答案 3 :(得分:2)

总的来说,这不起作用,因为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;

要使此强制转换工作正常,需要将转换运算符声明为subpoint subpoint需要有一个构造函数,该参数可以从{{1}转换为}。

答案 4 :(得分:1)

  

这些演员有什么问题?

您尝试这样做的事实。 point不是subpoint,如果有效,我会感到惊讶。

答案 5 :(得分:0)

a无法变为subpoint。那个实现不存在。