2008-12-13 40 views
3

爲什麼會發生這種情況?有趣的C++抽象函數

當U創建在C + +實施例的抽象類:即B類A類(其具有純虛函數) 從類繼承的

如果類A具有構造函數名爲A() 假設我創建了對象B類然後編譯器初始化基類,即class A然後初始化class B然後.......?

首先,我們不能訪問沒有Object的任何類的構造函數,那麼如果我們不能創建抽象類的對象,它如何初始化抽象類的構造函數。

回答

8

快速回答:構造函數是特殊的。

當A的構造函數仍在運行時,正在構造的對象還不是真正的A類型,它仍在構造中。當構造函數完成時,它現在是A.對於派生的B,它是相同的.A的構造函數首先運行。現在它是A.然後B的構造函數開始運行。在這期間,對象仍然是一個答案。只有當B的構造函數完成後,它纔會變爲B.

您可以通過嘗試從構造函數調用純虛函數來驗證這一點。如果函數在A中定義,並且B的構造函數調用它,則會出現運行時錯誤,而不是運行B的覆蓋,因爲對象不是B類型。

由於純虛擬函數,編譯器不允許生成構造A的代碼。但是它會生成代碼來構建一個A,作爲構建B的過程的一部分。這裏沒有涉及的魔術。你不能構造A的規則是由語言規則強加的,而不是物理的。語言升降機下B.

4

class A是抽象的,但是class B不是。爲了構建class B,它必須實現class A的所有純虛擬成員函數。

class A 
{ 
public: 
    A() {} 
    virtual ~A() {} 
    virtual void foo() = 0; // pure virtual 
    int i; 
}; 


class B : public A 
{ 
public: 
    B() {} 
    virtual ~B() {} 
    virtual void foo() {} 
    int j; 
}; 

A類佈局可能是這樣的:

 
+---------+  +---------+ 
| vftable | --> | ~A() | --> address of A::~A() 
+---------+  +---------+ 
| i  |  | foo() | --> NULL, pure virtual 
+---------+  +---------+ 

的B級佈局可能是這樣的:

 
+---------+  +---------+ 
| vftable | --> | ~B() | --> address of B::~B() 
+---------+  +---------+ 
| i  |  | foo() | --> address of B::foo() 
+---------+  +---------+ 
| j  | 
+---------+ 
+0

感謝您的答案,但我想知道它是如何創建抽象類的內部對象?????? – 2008-12-13 09:59:57

+0

對一個簡單問題的精心解答可笑。 – 2008-12-13 17:11:35

1
struct A { 
    A(int x) {..} 
    virtual void do() = 0; 
}; 

struct B : public A { 
    B() : A(13) {}  // <--- there you see how we give params to A c'tor 
    virtual void do() {..} 
}; 
0
And if class A has constructor called A() suppose i created an 
Object of class B then the compiler initializes the base class 
first i.e.class A and then initialize the class B 
Then.......? 

事實上的構造對象的特殊情況這條規則,你有它周圍的錯誤的方式:

當你創建類B的對象B的構造函數叫做。
如果不指定B構造函數是如何調用構造函數,則編譯器會自動插入在初始化列表中的第一個動作A.

的默認構造函數的調用如果你不想使用默認構造函數,您必須明確地將調用放到適當的A構造函數中作爲初始化程序列表中的第一個元素。

當A的建設完成後,B的建設將繼續進行。

First thing is we can not access a constructor of any class without an Object 
then how it is initialize the constructor of abstract class if we can not create 
an object of abstract class . 

你把上面的話說得像是考慮A和B不同的事情。 B類的一個對象也是A類的一個對象。它是整個對象是有效的。整個對象是B類,但它包含(作爲同一對象的一部分)來自A類的所有信息。

0

僅僅因爲您不能直接實例化類A並不意味着不可能實例化類A。你不允許實例化A,因爲編譯器知道A是抽象的,並且拒絕你編寫的任何代碼,試圖直接實例化A。它禁止這樣的代碼:

A a; 
new A(); 

什麼使一個類的抽象是它有純虛擬方法。不過,沒有什麼內在地阻止這樣的類被實例化。 C++標準只是說它不被允許。編譯器完全能夠生成指令來實例化抽象類。它所要做的就是保留適量的內存,然後調用構造函數,就像它爲非抽象類一樣。

當您實例化B時,該類的所有內存都被一次性分配。由於所有字節都存在,因此基本上有一個A實例,可以由構造函數初始化。 (但請注意,內存沒有正式考慮A類型的對象,直到A構造已經完成運行。)的A構造函數運行,然後B構造運行。