2009-05-06 24 views
2

に私はこのようになりますいくつかのコードを見直しされています:遅延コンストラクタC++

class A; // defined somewhere else, has both default constructor and A(int _int) defined 
class B 
{ 
public: 
    B(); // empty 
    A a; 
}; 

int main() 
{ 
    B* b; 
    b = new B(); 
    b->a(myInt); // here, calling the A(int _int) constructor, 
    //but default constructor should already have been called 
} 

は、この仕事をしていますか?デフォルト後に特定のコンストラクタを呼び出すと、既に呼び出されていますか?

答えて

15

そのコードは、コンストラクタを呼び出しません。それはA::operator()(int)を呼び出します。

あなたが明示的に作成されたオブジェクトのコンストラクタを呼び出す場合は、未定義のビヘイビアが存在します。実際にはうまくいくように見えるかもしれませんが、期待通りの行動を取るという保証はありません。

+0

このような場合があります。ありがとうございます。 –

+0

関数が宣言されている場合は、 "A :: operator()(int)"を呼び出すだけですか?私はあなたがこの機能が宣言されたと判断できることに感心しました! –

+2

@リチャード:あなたが何を得ているのか分かりません。関数が宣言されていない場合、コードはコンパイルされません。したがって、コード*がコンパイルされると仮定すると、演算子を定義する必要があります。 あいまいさはありません。使用されている構文がコンストラクタを呼び出すことはできません。これを行うには、代わりにb-> a :: myIntを書く必要があります。 Richの質問に表示される構文はoperator *()のみを呼び出すことができます。 – jalf

1

これはコンストラクタを呼び出すのではなく、this答えが何が起こっているかの唯一の可能な説明をカバーしています。 (以前のインスタンスが破壊された後)

既存のオブジェクトのコンストラクタを呼び出すための唯一の標準的な方法は、新しい配置を使用することです:

void foo (A * a) { 
    a->~A();   // Destroy previous instance 
    new (a) A(myInt); // Construct new object in same location 
} 
+0

コンポーザーに副作用がある場合(たとえば、ライブオブジェクトの数を数えて)、プレースメントnewが危険です。デフォルトのメモリ管理システムを置き換えることを意図しているのが最善です。 – Ari

+0

@Ari。確かに。しかし、すでに構築されているオブジェクトのコンストラクタを呼び出す唯一の方法です(それがあなたがやろうとするものなら)。 –

+0

実際には、まずオブジェクトを構成解除する必要があります。b-> a。〜A();新しいプレースメントの前にプレースメントnewは生の整列したメモリ上でのみ動作します。 – MSalters

2

あなたはクラスBで別のコンストラクタを作ることができます

B(INT _int):その場合(_int) {}

もし B =新しいB(ミン)を書き込みます。上記のコード

あなたはB-を呼び出す必要がいけないクラスA

のコンストラクタコードを遅らせないであろう>(ミント)

+0

これは正当なC++ではありません。あなたはあなたの答えから「はい」を取り除かなければなりません。そうしないと、印がついてしまうかもしれません。 –

+0

@リチャードコーデン:done –

+1

このコメントにはC++が表示されません – piotr

0

あなただけのBの中からA(INT)コンストラクタを呼び出す必要があります()コンストラクタを呼び出すか、A(int)コンストラクタを呼び出してB(int)コンストラクタを作成します。

ベストプラクティスは、Aのデフォルトのintを設定するデフォルトのものと、init A(int)のB(int)の両方を持つことです。