C++ 如果函数是从抽象类派生的,则无法使用具体类指针调用该函数

C++ 如果函数是从抽象类派生的,则无法使用具体类指针调用该函数,c++,segmentation-fault,abstract-class,C++,Segmentation Fault,Abstract Class,我正在使用g++Ubuntu/Linaro 4.6.3-1ubuntu5 4.6.3来运行我的代码。这两个程序都是经过编译的 一,。 以下程序在运行时出现分段错误 当一个抽象方法定义的类现在是具体的类时,为什么会观察到这种行为 二, 若类不是从抽象类派生的,那个么它在这里工作 class A { public: void func() { cout << "func()" << endl; } }; int main() { A *ao; ao-&g

我正在使用g++Ubuntu/Linaro 4.6.3-1ubuntu5 4.6.3来运行我的代码。这两个程序都是经过编译的

一,。 以下程序在运行时出现分段错误

当一个抽象方法定义的类现在是具体的类时,为什么会观察到这种行为

二, 若类不是从抽象类派生的,那个么它在这里工作

class A {
  public:
    void func() { cout << "func()" << endl; }
};

int main() {
  A *ao;
  ao->func();
  return 0;
}
当你使用

A *ao;
ao->func(); //--> Segmentation fault
ao未初始化为指向有效对象。对这样的指针调用成员函数会导致未定义的行为。在您的案例中,这表现为分段错误

它在没有抽象基类的情况下工作的事实是未定义行为的意外结果,在这种情况下似乎是正常的行为


实际上,这种看似正常的行为是由于您在调用中没有使用a的任何成员变量。对于抽象基类,使用虚拟表。由于指针未初始化为指向有效对象,因此尝试访问虚拟表会导致分段错误。

您使用未初始化的指针时会出现未定义的行为,因为它就像被分配了有效对象的地址一样。编译器不会为您检查,而是由您将其指向合理的位置

你所做的有点像是把一封信扔进邮箱而没有在上面写地址——谁知道会发生什么

您可能会从第一个,但不是第二个,得到一个分割错误,但是这不是由C++标准保证每次运行程序时发生的,更不用说如果你重新编译它,改变编译器参数,修改代码,尝试另一个编译器等等。 在实践中,当函数不是虚拟函数时,您之所以能够侥幸逃过一劫,可能是因为被调用的函数func没有尝试通过伪this指针访问任何对象数据,而伪this指针传递给它,它将接受ao的值:因此,指针是垃圾并不重要。当函数是虚拟的时,它尝试使用this指针来查找指向虚拟分派表的指针,但是垃圾指针实际上会咬人,程序会崩溃。如上所述,这两种行为都不能保证——它是未定义的

ao将有一些垃圾值,当您尝试ao->func时,您正在尝试访问ao指向的内存,因为很可能您没有访问该内存的权限,因此会出现内存分段错误。

A *ao = new A;
ao->func();
then its working

新运算符将为的实例分配内存,并返回指向ao的有效指针,因此它将正常工作。

您的所有示例都有未定义的行为。有关StackOverflow的问题都使用Markdown编写。请学习使用标记并正确格式化代码示例-这并不难。@πάνταῥεῖ: 就显示所希望的文本和表面上不做任何意外的事情而言,它可能确实起作用了——这与编码方式不同,编码方式可以保证它不会做任何意外的事情,甚至在下次运行时也会做同样的事情。假装不了解埃利努斯的工作方式无助于弄清事情的真相。。。。
A *ao;
ao->func(); //--> Segmentation fault
A *ao = new A;
ao->func();
then its working