动态地将基类型转换为派生类型。调用非虚函数但虚函数导致分段错误

时间:2015-05-24 19:03:35

标签: c++ casting virtual

以下是我的代码的简化形式

#include <iostream>

class base
{
  public:
  void func1() 
  {
    std::cout<<"In base func1"<<std::endl;
  }
  void func2()  
  {
    std::cout<<"In base func2"<<std::endl;
  }

  virtual void func4()
  {
    std::cout<<"In base func4"<<std::endl;
  }

  virtual void func5()
  {
    std::cout<<"In base func5"<<std::endl;
  }
};

class derived : public base
{
  public:
  void func1()
  {
    std::cout<<"In derived func1"<<std::endl;
  }

  void func3()
  {
    std::cout<<"In derived func3"<<std::endl;
  }

  void func5() 
  {
    std::cout<<"In derived func5"<<std::endl;
  }
};

int main()
{
  derived* ptr = dynamic_cast<derived*>(new base());

  if(ptr == NULL)
  {
    std::cout<<"Cast failed"<<std::endl;
  }

  ptr->func1();
  ptr->func2();
  ptr->func3();
  ptr->func4();
  ptr->func5();

  delete ptr;
}

将基础对象动态转换为派生类型会返回NULL指针。这应该导致ptr-> func1()的分段错误。我的输出是

Output:
Cast failed
In derived func1
In base func2
In derived func3

当ptr-&gt; func4()尝试执行时代码崩溃。 如果指针为NULL,则访问虚拟或非虚拟的任何函数都应该给出分段错误。有人可以解释处理这两种类型的区别。

enter image description here

2 个答案:

答案 0 :(得分:4)

您的主张,

  

这会导致ptr->func1()的分段错误。

完全没有事实根据,确实是错误的。没有&#34;分段错误&#34;在C ++语言中,没有什么可以保证在未定义行为的情况下发生任何类型的崩溃,这就是你所拥有的。您的程序的行为根本不是由C ++语言定义的。这与被定义为崩溃不同。

答案 1 :(得分:1)

Kerrek SB's answer是100%正确的。

为了让您更深入地了解dynamic_cast<derived*>在第一位失败的原因,您应该注意base实例不是derived。有效的动态强制转换代码的更好示例可能是:

base* b = new derived();
derived* ptr = dynamic_cast<derived*>(b);

这就是dynamic_cast<>的实际目的。您无法使用base将已存在的derived实例奇迹般地将其类型更改为dynamic_cast<>,它必须已是此类型的实例。