2012-04-10 63 views
0

明天早上我正在爲自己的考試做準備。我正在努力處理下面的C++演練。 我已經運行代碼並使用cout來檢查程序的執行情況。我注意到第一件事,那就是程序在類「one」中爲默認的構造函數調用了3次,只是爲main中的第一個對象調用。我對代碼的執行感到困惑。如何知道在C++中有2個類時使用哪個類?

#include <iostream> 
    using namespace std; 

    class one { 
    int n; 
    int m; 
     public: 
    one() { n = 5; m = 6; cout << "one one made\n"; } 
    one(int a, int b) { 
     n = a; 
     m = b; 
     cout << "made one one\n"; 
    } 
    friend ostream &operator<<(ostream &, one); 
    }; 

    ostream &operator<<(ostream &os, one a) { 
    return os << a.n << '/' << a.m << '=' << 
    (a.n/a.m) << '\n'; 
    } 

    class two { 
    one x; 
    one y; 
     public: 
    two() { cout << "one two made\n"; } 
    two(int a, int b, int c, int d) { 
     x = one(a, b); 
     y = one(c, d); 
     cout << "made one two\n"; 
    } 
    friend ostream &operator<<(ostream &, two); 
    }; 

    ostream &operator<<(ostream &os, two a) { 
    return os << a.x << a.y; 
    } 

    int main() { 
    two t1, t2(4, 2, 8, 3); 
    cout << t1 << t2; 
    one t3(5, 10), t4; 
    cout << t3 << t4; 
    return 0; 
    } 

我不明白第一件事。當主要調用第一個默認構造函數two t1,爲什麼它被連續調用三次然後它會調用t2(4, 2, 8, 3);

如果代碼太長,我很抱歉,但我真的需要幫助才能理解它。

請指教。謝謝。

+0

請詳細說明你的問題,你不能從這個代碼明白什麼? – SMK 2012-04-10 05:01:33

+0

C++允許特定的優化,在某些情況下,編譯器可能會刪除臨時對象。這使得更難預測將調用多少構造函數。編譯器在調試時會留下額外的ctor調用是很常見的,但在最終版本中刪除它們。 – MSalters 2012-04-10 07:28:44

回答

4

我得到這樣的結果,當我運行代碼:

one one made 
one one made 
one two made 
one one made 
one one made 
made one one 
made one one 
made one two 

這是因爲:

two t1; 
one one made //t1.x; parameterless 'one' constructor called by default 
one one made //t1.y; parameterless 'one' constructor called by default 
one two made //t1; parameterless 'two' constructor 

t2(4, 2, 8, 3) 
one one made //t2.x; default constructor as variable not present in initialization list 

one one made //t2.y; default constructor as variable not present in initialization list 

made one one //x = one(a, b) executed now 
made one one //y = one(c, d) executed now 
made one two //t2(int..) constructer called 

注意,X和Y在T2的情況下構建的兩倍有沒有初始化列表。爲了避免這種情況,你可以使用:

two(int a, int b, int c, int d): x(a,b), y(c,d) 
{ 
cout << "made one two\n"; 
} 
+0

好,只是爲了澄清這一點。所以,因爲它必須在x中調用默認的構造函數「one」,並且它必須在「two」中調用它自己的默認構造函數,這就是爲什麼我最終得到t1對象,在「one」中調用兩次,在「two 「, 對? – Jack 2012-04-10 05:44:25

+1

是的。只要你創建一個'two'對象,它的所有成員變量都將默認構造(在這種情況下,x和y)。在此之後,構造函數的主體被執行:「cout <<」一個兩個\ n「;」現在t1的構造完成了。 – vid 2012-04-10 06:00:21

2

由於創建了兩個對象的THREE實例,您將看到發生三次的類「one」和類「two」的構造函數。

如果仔細查看插件友元函數,類1和類2都通過值而不是通過引用傳遞。一個臨時實例必須通過缺省拷貝構造函數創建(您尚未實現)。如果你想廢除多餘的實例,改變你的插件功能,這樣的:

friend ostream &operator<<(ostream &, one &obj); 
friend ostream &operator<<(ostream &, two &obj); 

和我看得更遠,二有一個2個型成員變量,所以我想你會看到更多的建設者。

最後,像這樣的測試類應該被命名爲foo和bar。即使對自己也難以溝通。 (恕我直言)

+0

謝謝。我看到你在說什麼,但是這個代碼是由老師提供的。 – Jack 2012-04-10 05:12:26

+0

好的,但爲什麼當它說兩個t1時,我們不會調用兩個默認構造函數? – Jack 2012-04-10 05:17:55

+1

我懷疑如果你要在調試器中遍歷代碼,你會看到兩個構造函數被調用。我現在在這裏使用我的大腦調試器,不過我只能這麼肯定。 :) – 2012-04-10 05:56:23

1

從在main.Two默認構造你的第一個對象「一」叫,因爲類「二」類有「一」和一個默認的構造函數的兩個對象被稱爲的「兩個」是正常的。

1

這裏是輸出,我看到:

one one made
one one made
one two made
one one made
one one made
made one one
made one one
made one two
5/6=0
5/6=0
4/2=2
8/3=2
made one one
one one made
5/10=0
5/6=0

它使我感覺良好。我沒有看到第一個對象被調用3次的默認構造函數。

至於輸出去,這裏發生了什麼:

two t1, t2(4, 2, 8, 3);

對於T1,它會調用一個默認的構造方法,無論是在類中定義的對象

two (one x and one y)

所以輸出是「one one made」和「one one made」 接下來它執行兩個 的默認構造函數,所以輸出是「做一個兩個」下一步T2 ,它再次調用一個兩個x的默認構造函數和y 所以輸出是「一個一個做」和「做一個一」 接下來,它執行

x = one(a,b) and y =one(c,d)

所以現在它打印「作了一一」,並在兩個()正如我們「做一個兩個」一樣被打印的構造函數「做出一一」 現在......

cout << t1 << t2; 

one t3(5, 10), t4; 

對於這個語句再次爲t3,它調用一個構造函數並打印「made o NE一個」 而對於T4它執行默認的構造函數,並打印‘一個一個做’

cout << t3 << t4; 
相關問題