簡體   English   中英

如果它是從抽象類派生的,則無法使用具體的類指針調用函數

[英]Not able to call function with concrete class pointer, if it is derived from abstract class

我正在使用“ 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;
}

使用時

A *ao;
ao->func(); //--> Segmentation fault

ao未初始化為指向有效對象。 在此類指針上調用成員函數會導致未定義的行為。 在您的情況下,這表現為分段錯誤。

在沒有抽象基類的情況下它起作用的事實是未定義行為的意外結果,在這種情況下,這似乎是理智的行為。

實際上,看似理智的行為是由於您沒有在調用中使用A任何成員變量而導致的。 在抽象基類的情況下,使用虛擬表。 由於指針未初始化為指向有效對象,因此嘗試訪問虛擬表會導致分段錯誤。

您具有未定義的行為,因為您使用的是未初始化的指針,就好像它已被分配了有效對象的地址一樣。 編譯器不會為您檢查-取決於您將其指向合理的位置。

您所做的有點像在信箱中放一封信但未在上面寫地址-誰知道會發生什么?

您可能會從第一個而不是第二個中得到分段錯誤,但是C ++標准不能保證每次運行程序時都會發生分段錯誤,更不用說重新編譯,更改編譯器參數,修改代碼,嘗試另一個編譯器了。等等..

在實踐中,你是發生在“逃脫”的程度時,函數不是虛擬的原因可能是被調用的函數func沒有試圖通過偽造的訪問任何對象數據this指針傳遞給它(這將在來自ao的值):因此指針的垃圾無關緊要。 當該函數為virtual函數時,它將嘗試使用this指針查找指向虛擬調度表的指針,但隨后垃圾指針實際上被咬住,程序崩潰。 如上所述,兩種行為都不能得到保證-它是undefined

A *ao;
ao->func(); //--> Segmentation fault

ao將具有一些垃圾值,當您嘗試ao-> func()時,您嘗試訪問ao指向的內存,並且由於很可能您無權訪問發生內存分段錯誤的權限。

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

new運算符將為A的實例分配內存,並將有效指針返回到ao,因此它將正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM