2015-02-24 104 views
5
#include <iostream> 
struct A 
{ 
    A(){std::cout<<"A()"<<std::endl;} 
}; 

template<typename T> 
struct B 
{ 
    A a; 
    T b; 
    B(){std::cout<<"B()"<<std::endl;} 
}; 

int main() 
{ 
    B<B<B<int> > > Test; 
    return 0; 
} 

的調用構造函數的odrer是訂單在一種情況下C++調用構造函數

A() 
A() 
A() 
B() 
B() 
B() 

而且我不知道這是爲什麼。我認爲這將是A B A B A B.你能解釋我爲什麼嗎?

+3

成員變量初始化。 – immibis 2015-02-24 21:49:19

回答

2

這實際上是直線前進,如果是像ABABAB,那麼你將有麻煩,如果你想從B構造訪問b,因爲你認爲爲了意味着第一個成員a被實例化,然後ctor運行,然後b被初始化。實際上,每個成員都先實例化(構造等),然後調用構造函數。

1

這是因爲成員變量必須在構造函數的主體執行之前被初始化。請看下面的例子:

struct A { 
    int value; 

    // Here we explicitly initialize 'value' with 5 
    A() : value(5) { } 
}; 

struct B { 
    A a; 

    B() 
    { 
     // This is perfectly valid and would print 5, 
     // because 'a' has already been implicitly initialized 
     // with its default constructor. 
     std::cout << a.value; 
    } 
}; 

如果不是這種情況,你會想到什麼價值a有在B的構造?你會遇到各種問題。因此,A的默認構造函數必須在B()的主體之前隱式調用。

本質,使之更加明確,這就是正在發生的事情:

// Initialize 'a' before body of constructor 
    B() : a() 
    { 
     std::cout << a.value; 
    } 
1

首先,我們來分析一下你有什麼樣的位置:

  • 你有Testclass B<B<B<int> > >對象,它是:

    class B<B<B<int> > > { 
        A a; 
        B<B<int> > b; 
    }; 
    
  • the seco的Test第二字段,Test.bclass B<B<int> >,它是:

    class B<B<int> > { 
        A a; 
        B<int> b; 
    }; 
    
  • 那麼你的Test.b第二場,Test.b.b,這是class B<int>,它是:

    class B<int> { 
        A a; 
        int b; 
    }; 
    

所以初始化的順序是:

  • A()對於Test.a
  • A() for Test.b.a
  • A()對於Test.b.b.a
  • 沒有構造函數作爲Test.b.b.bint類型,並且沒有構造函數。
  • B<int>()對於Test.b.b
  • B<B<int> >() for Test.b
  • B<B<B<int> > >()對於Test

不幸的是,所有這三個構造函數在輸出時都寫同樣的東西:B(),但它們對於不同的類是不同的構造函數。

+0

可以顯示嵌套:http://ideone.com/45rDMR – stefan 2015-02-26 13:05:48

+0

是的,但是您打印的順序相反,首先打印最嵌套的'b'字段。順序可能是'B()2','B()1','B()0'。 – 2015-02-26 13:10:39

+0

我不明白你在說什麼。這個命令是B (),B >(),...所以顯示的數字是正確的:第一次調用B 對象的構造函數是B (),因此B()0是正確的首先打印。順序完全不同,它的定義很明確。 – stefan 2015-02-26 13:14:34

0

這是預期的行爲,因爲成員初始化發生在構造函數的主體之前。爲了實現這一點,是有幫助的添加成員初始化以及:

template<typename T> 
struct B 
{ 
    A a; 
    T b; 
    B() 
    : 
     a(), 
     b() 
    { 
     std::cout<<"B()"<<std::endl; 
    } 
}; 

完全掌握執行的順序,讓我們添加一個空整數字段。 我也添加了一個模板來顯示嵌套。演示請參閱http://ideone.com/KylQQb

#include <cstdio> 

struct A 
{ 
    A() 
    : 
    dummy(printf("Starting to construct A()\n")) 
    { 
     printf("Fully constructed A()\n"); 
    } 
    int dummy; 
}; 

template <typename T> 
struct Nesting; 

template <> 
struct Nesting<int> 
{ 
    constexpr static int value = 0; 
}; 

template <template <typename> class T, typename I> 
struct Nesting<T<I>> 
{ 
     constexpr static int value = 1 + Nesting<I>::value; 
}; 

template<typename T> 
struct B 
{ 
    int dummy; 
    A a; 
    T b; 
    B() 
    : 
    dummy(printf("Starting to construct B() with nesting %d\n", Nesting<B<T>>::value)), 
    a(), 
    b() 
    { 
     printf("Fully constructed B() with nesting %d\n", Nesting<B<T>>::value); 
    } 
}; 

int main() 
{ 
    B<B<B<int>>> Test; 
    return 0; 
} 

這樣做的輸出將是構造函數體運行之前

Starting to construct B() with nesting 3 
Starting to construct A() 
Fully constructed A() 
Starting to construct B() with nesting 2 
Starting to construct A() 
Fully constructed A() 
Starting to construct B() with nesting 1 
Starting to construct A() 
Fully constructed A() 
Fully constructed B() with nesting 1 
Fully constructed B() with nesting 2 
Fully constructed B() with nesting 3 
+0

我覺得你有點困惑。構造函數不會被調用,中間會調用其他構造函數。構造函數是一個線程和序列化的一個對象被完全構建。 – 2015-02-26 13:35:17

+0

@LuisColorado我一點也不困惑。也許命名不是那麼好,但是這就是發生了什麼以及標準定義的內容。 – stefan 2015-02-26 13:36:47

相關問題