2016-12-01 6 views
2

は、次のコードを検討してください。クラスCのコンストラクタをメンバ変数よりも早く呼び出す方法があれば問題になるでしょうか? タクシーのと解体私はクラスの道最初のコンストラクタは、メンバ変数、その後に呼び出される順序を変更することができる方法BACクラス内のメンバ変数より早くコンストラクタを呼び出すことができますか? 私はあなたがクラスCのオブジェクトを作成するときに最初のメンバ変数は、建設の順序は<strong><em>ABC</em></strong>と解体<strong><em>CBA</em></strong>になり、その後構築されることを知っている:

の注文を持っています。

#include <iostream> 
#include <exception> 

class A { 
public: 
    A() { 
    std::cout << 'a'; 

    } 
    ~A() { std::cout << 'A'; } 
}; 


class B { 
public: 
    B() { std::cout << 'b'; } 
    ~B() { std::cout << 'B'; } 

}; 

class C { 
public: 
    C() { 
    std::cout << 'c'; 

    } 
    ~C() { std::cout << 'C'; } 

    A m_a ; 
    B m_b; 
     }; 


void foo() { C c; } 

int main() { 
    try { 
    foo(); 
    } 
    catch (std::exception &) { 
    std::cout << "catch"; 

    } 
} 
+0

を確保します。しかし、あなたの元の問題に対する解決策がまだあるかもしれません - あなたはその「初期建設」の中で何をしますか?それには何が必要ですか? – Quentin

+2

できません。メンバをダイナミックなスマートポインタにして、 'C :: C()'の本体の中でそれらを初期化することができます(これは本当にお勧めできません)。それを超えると、オプションは指定されたコードにはほとんど存在しません。私はあなたが言語そのものの機能を回避しようとする理由があると確信しています(オブジェクトが完全に構築されるまでオブジェクトは機能構築を開始できません)。しかしこれは[XY問題]の強い香りですmeta.stackexchange.com/questions/66377/what-is-the-xy-problem)。 – WhozCraig

答えて

2

実際に建設注文を破ること(これは不可能)の回避策が増えています。スマートポインタでメンバーを格納します。あなたが気に実際のオブジェクトの

class C { 
public: 
    C() { 
    std::cout << 'c'; 
    m_a = std::make_unique<A>(); 
    m_b = std::make_unique<B>(); 
    } 
    ~C() { 
    m_b.reset(); 
    m_a.reset(); 
    std::cout << 'C'; 
    } 

    std::unique_ptr<A> m_a; 
    std::unique_ptr<B> m_b; 
}; 

インスタンスは今Cのコンストラクタの最後で作成することができます。もちろん、あなたはダイナミックなメモリ割り当てを行うことでそれを支払うでしょう。

別の解決策は、整列ストレージと配置新築使用することができます。

class C { 
public: 
    C() { 
    std::cout << 'c'; 
    new(&m_a) A; 
    new(&m_B) B; 
    } 
    ~C() { 
    m_b.~B(); 
    m_a.~A(); 
    std::cout << 'C'; 
    } 

    std::aligned_storage<sizeof(A), alignof(A)>::type m_a; 
    std::aligned_storage<sizeof(B), alignof(B)>::type m_b; 
}; 

をしかし、あなたが持っているいずれかの方法は、非常に注意が必要とrule of three/fiveに従うこと。

+2

'm_a.reset();を追加することをお勧めします。 m_b.reset(); 'もまた目的の出力を達成するためにデストラクタ内にあります。 – Quentin

1

それとも単に:

class C { 
public: 
    A *m_a; 
    B *m_b; 

     C() { 
     std::cout << 'c'; 
     m_a = new A; 
     m_b = new B; 
     } 
    ~C() { 
     delete m_b; 
     delete m_a; 
     std::cout << 'C'; } 
     }; 

使用スマートポインタの答えは「ノー」である、あなたは、コンストラクタ本体は、メンバー初期化子の前に呼ばれるように得ることができない例外安全性

関連する問題

 関連する問題