将基类指针转换为派生类指针

时间:2019-06-27 16:16:15

标签: c++ casting

如以下代码所示,我正在尝试将基类指针转换为派生类指针。我期待以下代码产生编译器错误,但不会报告任何错误。还有功能“ SomeMethod_2”打印值10。

{
  for item in stack
  {
    print(item)
  }
}

3 个答案:

答案 0 :(得分:2)

强制类型转换,尤其是C风格的强制类型转换,告诉编译器关闭许多错误和警告,并保证您自己知道自己在做什么,后果自负。

在大多数情况下,使用不指向该类型对象的指针是未定义行为。未定义行为仅是-对可能发生的事情没有任何要求,因此您可能会遇到编译器错误或运行时错误。或者,您可能似乎认为它“起作用”(可能意味着什么),或者完全出乎意料的事情。

就您的特定情况实际发生的情况而言,这些函数很可能使用不属于*BaseObj的相邻存储器来存储int,但是事后没关系。但是,如果您记得delete对象,那么此时可能会遇到问题,因为堆内存管理功能可能已经使用了覆盖的内存。

请注意,如果Base具有至少一个虚函数(如析构函数),并且您使用了更安全的dynamic_cast而不是最不安全的C样式强制转换,则强制转换的结果将是空指针,因为dynamic_cast会检查对象是否实际上属于该类型。

class Base {
public:
    Base() {
        cout << "Base class constructor\n";
    }
    virtual ~Base() = default;
};

// ...

int main()
{
    Base* BaseObj = new Base();

    Derived* DerivedObj = dynamic_cast<Derived*>(BaseObj);

    if (DerivedObj) {
        DerivedObj->SomeMethod();
        DerivedObj->SomeMethod_1();
        DerivedObj->SomeMethod_2();
    } else {
        std::cout << "Not a Derived\n";
    }

    delete BaseObj; // Don't forget to match every "new" with a "delete".
    return 0;
}

答案 1 :(得分:1)

您刚刚执行了Base *到Derived *的c样式转换。 函数SomeMethod是在Derived类中定义的,因此通过Derived *进行的调用是合法的,而不是编译时错误。成员函数不是类实例的一部分,而是将它们放置在代码段中,并且可以通过隐藏此参数来调用特定实例的成员函数。如果您没有数据成员,那么甚至都不会发生切片。在指针强制转换之后检查指针是否转换为有效指针总是一个好主意。当然,在c ++中,对于这种用例,我们使用dynamic_cast。

答案 2 :(得分:1)

Derived* DerivedObj ....
DerivedObj->SomeMethod();    # Expecting compiler error
     

我正在期待编译器错误

没有理由在这里出现编译器错误。 DerivedObj是指向Derived的指针,该指针具有成员函数SomeMethod,因此函数调用的格式正确,需要编译器才能成功对其进行编译。

现在,通过指针DerivedObj进行间接调用并调用成员函数的行为是否已正确定义,取决于指针是否有效。在这种情况下无效,因此程序的行为是不确定的。

  

还有函数“ SomeMethod_2”打印值10。

这是未定义行为的示例。