2012-12-07 131 views
0

編輯:沒有任何代碼是我的,它全部都給了我,我只是從對象分配方法的角度分析它。C++內存分配 - 分配子類到

我在內存分配方面非常辛苦。我向你保證,在過去的5個小時裏,我已經看過這裏的一百個例子。我知道這可能措辭不佳,我提前道歉。

1.)我不明白爲什麼版本2打印類A的f()而不是類B的。行

A* objA1 = objB; 

被聲明一個指針,objA1,它指向類型A的一個對象,它是分配其地址到objB指向,B(2,3)。我讀過「如果它們是堆 - 動態對象,那麼你可以將b1分配給a1」。當我打電話給objA1-> f()時,我只是說去這個地方,哦,你找到了一個B?把它投入A並調用f()。

2.)我會認爲版本1切片objB,因爲它是說這個對象已被分配空間A,等於B更大。但如果我把cout < <objB.bf;在此作業之後,它仍然有效。是一個objA1 = objB;不是靜態聲明objA1?再一次,爲什麼不打印B的f()?

3.)兩個objA1作業有什麼區別?因爲哪些功能只適用於兩者之一。如果你想給它一個過時的分類分類,你可以稱它們爲「堆 - 動態」嗎?

class A { 
    private: 
    int a; 
    public: 
    A(int ia) {a = ia;} 
    void f() { 
     cout << "Call to method f defined in class A" << endl; 
    } 
}; 
class B : public A { 
    private: 
    int b; 
    public: 
    B(int ia, int ib) : A(ia) {b = ib;} 
    void f() { 
     cout << "Call to method f specialized in class B" << endl; 
    } 
    void bf() { 
     cout << "Call to class B own method bf" << endl; 
    } 
}; 
// C++ driver - Version 1 
void main() { 
    A objA = A(1); 
    B objB = B(2,3); 

    objA.f(); 
    objB.f(); 
    objB.bf(); 

    A objA1 = objB; 
    objA1.f(); 
} 

// C++ driver - Version 2 
void main() { 
    A* objA = new A(1); 
    B* objB = new B(2,3); 

    objA->f(); 
    objB->f(); 
    objB->bf(); 
    A* objA1 = objB; 
    objA1->f(); 
} 
+0

'main'返回'int',而不是'void'。 – GManNickG

回答

1

默認情況下,C++不使用動態分派。這意味着,當p宣佈爲X *p時,將調用p->f()總是調用X::f(),而不管p指向的實例的動態類型如何。要啓用動態調度,該功能必須聲明爲virtual。這與Java/C#形成鮮明對比,其中所有成員函數都隱式地爲virtual

確實發生了「版本1」中的切片,但是,objB不受任何方式的影響。它是objA受切片影響(即它忽略objB的不屬於A的部分)。

+0

你能幫我瞭解兩個objA1任務之間的區別嗎?因爲哪些功能只適用於兩者之一。如果你想給它一個過時的分類分類,你可以稱它們爲「堆 - 動態」嗎? –

+0

@ caleb.breckon'A objA1 = objB;'(其中'objB'類型爲'B')在堆棧上創建類型爲'A'的對象'objA1'(變量的值就是對象本身)。 'a * objA1 = objB;'(其中'objB'是類型'B *')** **指針** - 賦值後,objA1和objB都指向相同'objB'的實例,它使用'new'在堆上分配。 – Angew

2

你需要聲明的是,你希望被稱爲多態(通過指針基地)作爲基類virtual的功能。當編譯器通過指向對象的指針(或引用)遇到對函數virtual的調用時,它將查找該對象的動態類型的函數,而不是靜態類型。因此,簡單地把virtual在函數定義的前面A

virtual void f() { 
    cout << "Call to method f defined in class A" << endl; 
} 

你行A objA1 = objB;確實切片您B對象,只是在複製它的A部分objA1。您只能在objA1上撥打A的會員功能。但是,objB仍然是它始終存在的相同對象 - 它仍然是B,並且具有B的所有可用成員函數。您可以愉快地撥打objB->bf(),但不是objA->bf()也不是objA1->bf()

如果有疑問,只要看看你打電話給你的功能對象的類型。如果是A,則只能撥打A的功能,並且也可以撥打B。如果您通過指針訪問並調用函數,則調用屬於對象dynamic type的函數(而不是指向它指向的指針的類型)。

+0

你能幫我瞭解兩個objA1任務之間的區別嗎?因爲哪些功能只適用於兩者之一。如果你想給它一個過時的分類分類,你可以稱它們爲「堆 - 動態」嗎? –

+0

@ caleb.breckon第一種方法是給'A *'分配一個'B *'指針 - 這非常好,並且不會發生對象切片,因爲您不復制它們指向的對象。然而,當你將一個「B」類型的對象賦給一個類型爲「A」的對象時,你實際上是在將一個對象的值拷貝到另一個對象上,而顯然「B」的值不能適合值一個'A',所以你得到物體切片。 –