如果从抽象类派生,则无法使用具体类指针调用函数
Posted
技术标签:
【中文标题】如果从抽象类派生,则无法使用具体类指针调用函数【英文标题】:Not able to call function with concrete class pointer, if it is derived from abstract class 【发布时间】:2015-08-28 05:28:08 【问题描述】:我正在使用“g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3”来运行我的代码。两者都是程序编译。
(1.) 以下程序运行时出现分段错误
#include <iostream>
using namespace std;
class Abstract
public:
virtual void func() = 0;
;
class A : public Abstract
public:
void func() cout << "func()" << endl;
;
int main()
A *ao;
ao->func(); //--> Segmentation fault`<br/>
/*
if we do
A *ao = new A;
ao->func();
then its working
*/
return 0;
当 A 现在是具体类时,为什么会观察到这种行为,因为它定义了 Abstracts 方法?
(2) 如果类不是从抽象类派生的,那么它就可以工作了。
class A
public:
void func() cout << "func()" << endl;
;
int main()
A *ao;
ao->func();
return 0;
【问题讨论】:
你所有的例子都有未定义的行为。 *** 上的问题是使用 Markdown 编写的。请学习使用 MarkDown 并正确格式化代码示例 - 这并不难。 【参考方案1】:当你使用时,
A *ao;
ao->func(); //--> Segmentation fault
ao
未初始化为指向有效对象。在这样的指针上调用成员函数会导致未定义的行为。在您的情况下,这表现为分段错误。
它在没有抽象基类时起作用的事实是未定义行为的意外结果,在这种情况下看似正常的行为。
实际上,看似正常的行为是因为您在调用中没有使用A
的任何成员变量。在抽象基类的情况下,使用虚拟表。由于指针未初始化为指向有效对象,因此尝试访问虚拟表会导致分段错误。
【讨论】:
@πάντα ῥεῖ:就显示希望的文本和表面上没有做任何意外的事情而言,它可能确实是“工作” - 这与编码不同这样可以保证它“不会做任何意外的事情”,甚至可以保证下次运行时它会做同样的事情。假装不理解 elinus 打算“工作”的方式无助于追根溯源......【参考方案2】:您有未定义的行为,因为您使用的是未初始化的指针,就好像它已被分配了有效对象的地址。编译器不会为您检查 - 由您将其指向合理的地方。
你所做的有点像把一封信丢到邮箱里却没有写地址——谁知道会发生什么?
您可能会从第一次遇到分段错误,但不是第二次,但 C++ 标准并不能保证每次运行程序时都会发生这种情况,更不用说重新编译它、更改编译器参数、修改代码、尝试其他编译器等。
实际上,当函数不是虚拟函数时,您碰巧“逃脱”它的原因可能是被调用函数func
没有尝试通过传递的虚假this
指针访问任何对象数据到它(它将采用来自ao
的值):所以指针的垃圾并不重要。当函数为virtual
时,它会尝试使用this
指针来查找指向虚拟分派表的指针,但随后垃圾指针实际上会咬人并且您的程序崩溃。如上所述,这两种行为都无法保证 - 它是 undefined。
【讨论】:
【参考方案3】:A *ao;
ao->func(); //--> Segmentation fault
ao 将有一些垃圾值,当您尝试 ao->func() 时,您正在尝试访问 ao 指向的内存,因为很可能您没有访问该内存分段错误的权限。
A *ao = new A;
ao->func();
then its working
new 运算符将为 A 的实例分配内存并返回指向 ao 的有效指针,因此它可以正常工作。
【讨论】:
以上是关于如果从抽象类派生,则无法使用具体类指针调用函数的主要内容,如果未能解决你的问题,请参考以下文章