なぜ私はC ++でそのクラスのインスタンスから私のクラスのコンストラクタを呼び出すことはできませんか?

StackOverflow https://stackoverflow.com/questions/2146901

  •  23-09-2019
  •  | 
  •  

質問

するとき、それは通常の関数だかのようにクラスのオブジェクトは、そのクラスのデストラクタを呼び出すことができますか?なぜそれがその通常の機能の一つとして、同じクラスのコンストラクタを呼び出すことはできませんか?なぜコンパイラはこれをやってから私たちを停止していますか?

例えば、

class c
{
public:
   void add() ;
   c();
   ~c() ;
};

void main()
{
 c objC  ;
 objC.add() ;
 objC.~c() ; // this line compiles
 objC.c() ;  // compilation error
}
役に立ちましたか?

解決

オブジェクトが作成されたときに

は定義することにより、コンストラクタは一度だけ呼ばれます。あなたは、オブジェクトへのアクセス権を持っている場合は、再度、コンストラクタを呼び出すことが許されていないので、作成されている必要があります - これは明示的なコンストラクタの呼び出しが許可されていない理由です。同様に、デストラクタは、オブジェクトが破壊されたときに、一度呼び出されなければなりません。これは、常に自動的に行うことができれば、その言語は、明示的なデストラクタの呼び出しを禁止します。

しかし、いくつかの状況で、あなたは正確なメモリ管理を制御し、明示的に作成し、管理していることをメモリ内のオブジェクトを破壊する能力が必要になる場合があります。この目的のために、言語が「新しい配置は、」任意の場所にオブジェクトを作成するために提供し、オブジェクトを破壊するための明示的なデストラクタの呼び出しは、このように作成しました。あなたの代わりに、「新しい配置を」得るよう - あなたは、新しいオブジェクトの場所を指定できるようにする必要があるため、明示的なコンストラクタ呼び出しは、有用ではありません。明示的なデストラクタ呼び出しは十分なので、「削除配置を」マッチングのいくつかの並べ替えを発明する必要はありません。

ので:それらが許可されていないので、明示的なコンストラクタ呼び出しのための有効な使用はありません。そこ明示的なデストラクタ呼び出しのための有効な使用は、ある彼らは(構文的に)許可されているので、あなただけの今までそう破壊されることはありませんオブジェクト上でそれらを使用しなければならないというルールで、つまりは「配置新しい」を使用して作成されたオブジェクト、およびその中ケースは一度だけそれらを呼び出します。コンパイルが、未定義の動作を与える、非常に多くのC ++のエラーのように、他の方法でそれらを使用します。

他のヒント

私はあなたのインスタンスが置き換えられていること/配置に呼び出し、新規に再作成してください場合は、明示的にデストラクタを呼び出すことができると思います

class c
{
public:
   void add() ;
   c();
   ~c() ;
};

int main()
{
 c objC  ;
 objC.add() ;
 objC.~c() ; // this line compiles
 new (&objC) c;  // placement new invokes constructor for the given memory region
}

(Cのコンストラクタは、地獄は、スタックアンワインド中に緩んで破損することがあり、その場合には、私が想像する、投げることができない限り)私は実際にこれを見たことがないが、論理的にそれが動作するはずです。

しかし、どのようなあなたはおそらくしたいことがちょうど割り当てです。

objC = c();

デストラクタは、あなたがに興味があるという副作用を持っている場合、デストラクタは「左手」の値に対して呼び出されるコピーおよびスワップイディオムを使用して割り当てを実装します。

Aデストラクタは、クラスの既存のインスタンスに呼び出さなければなりません - インスタンスを破壊することは、それが何をするかです。既存のインスタンス上で呼び出すことは意味がありませんので、コンストラクタは、クラスの新しいインスタンスを作成します。

これは、新規および削除の作業方法に似ています:

int * p = new int;    // call to new needs no existing instance
delete p;             // call to delete requires existing instance
あなたのコード内の

そしてノートでは、オブジェクトが明示的に、そして一度暗黙的にその外側のスコープの終わりに1回、2回破壊されてしまいます。あなたはおそらく、新しい配置の使用を含む、異常な何かをやっている場合は、一般的にのみ、明示的にデストラクタを呼び出します。

あなたは本当にこのような何かをする必要がある場合は、

は、単に追加の関数を作成し、外部からコンストラクタ自体からそれを呼び出すが、あなたは、このような呼び出しが必要なのかと何が起こるか見てみましょう。

#include<new>

class A
{
//members
};

int main()
{
//allocate buffer
char* buffer = new char[sizeof(A)];
//construct A on that memory space
A * ptrToA = ::new (buffer) A();
//destroy the object
ptrToA->~A();
//deallocate the buffer
delete[] buffer;
}
プレースメントの新しい使用法を見つけることができます。

1つのインスタンスが標準です コンテナ。アロケータは、割り当てに責任を取り込み バッファ(メンバー割り当て)とオブジェクトがその上に構築されています それらは容器に追加されるバッファ。たとえば、あなたが ベクトルオブジェクト上の準備金は、それが意味Nのオブジェクトのためのスペースを確保し Nのために割り当てスペースは、オブジェクトが、それらを構築しません。そして、とき あなたは、要素を追加するために、彼らはその一backなどの上に作成されません バッファ。基本的に、のオーバーヘッドを削減する技術であります メモリ割り当て関数への呼び出しを繰り返しました。そして行われたときに、 ベクトルデストラクタはデストラクタを呼び出すオブジェクトを破壊するであろう 明示的にその中のすべてのオブジェクトについて、次に()を呼び出して割り当て解除 アロケータの機能は、メモリを解放します。この情報がお役に立てば幸いです。

これを試してみます:

obj.ClassName ::クラス名(); //それはVC 6.0で動作するコンパイラ

制限について考えるもう一つの方法は、コンストラクタは、のないのちょうど別の関数であるということです。その定義を考えてみます。他の関数とは異なり、それは戻り値はありません、それは初期化子リストを有することができます。それだけで、ほとんどの関数の構文のは、偶然の一種である持っていることを起こること。それは本当に唯一のオブジェクトの新しいインスタンスを初期化する目的のために存在します。

コンストラクタが存在 "C()" 新しい、すなわち

で使用され
c objC = new c();
あなたは、クラスのインスタンスの実際の建設のあなたのコンストラクタの外を呼び出したい場合は、あなたはどちらか、コンストラクタの目的を理解していないか、それが存在してはならない存在に機能を配置しようとしている。

あなたはより多くの言語の制限よりも構文の特定のスタイルについて尋ねています。 C ++を使用すると、オブジェクトのコンストラクタまたはデストラクタを呼び出すことができます。

c objC;
objC.~c();  // force objC's destructor to run
new(&objC); // force objC's constructor to run

なぜ言語設計者は、代わりにこの構文を使用していませんでした?

c objC;
delete(&objC) c; // force objC's destructor to run
new(&objC) c;    // force objC's constructor to run

あるいは、なぜます:

c objC
objC.~c(); // force objC's destructor to run
objC.c();  // force objC's constructor to run

彼らは彼らがした構文を選んだ理由として私の意見: 最初の選択肢は、第二のより柔軟です。私は、任意のアドレスだけでなく、インスタンスのコンストラクタ/デストラクタを呼び出すことができます。その柔軟性がなく、破壊のため、割り当てのために必要とされています。また、最初のオプションの削除は、仮想デストラクタが混乱する中で得れば非常に危険と思われます。

あなたはtypeofを使用して、インスタンスのクラスのコンストラクタを呼び出すことができます:

class c
{
public:
   void add() ;
   c();
   ~c() ;
};

void main()
{
 c objC  ;
 objC.add() ;
 objC.~c() ; // this line compiles (but is a bad idea)
 typeof objC otherObjC;  // so does this.
}

これは、インスタンスobjCの値に影響を与えるが、otherObjCのクラスのコンストラクタを使用して、新しいインスタンスを作成しますobjCません。

注:これは、静的な型は、あなたが持っているインスタンスの動的な型の基底クラスであれば、あなたが期待していない何かを行うことができます。

あなたができないと言いますか?あなたはどれだけ知っている必要があります。

void Foo::Bar() {
  *this = Foo(); // Reset *this
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top