1

これは、インタビューの1つで私に尋ねられた質問でした。

Vtableがコンパイル時に作成されvptr、実行時にオブジェクトに割り当てられる場合、クラスに仮想コンストラクターがある場合、コンパイラーがコンパイル時エラーを発生させるのはなぜですか?

メカニズム全体を説明しました。しかし、彼は「ランタイムエラーではなくコンパイル時エラーが発生する理由」にもっと興味を持っていました。

私は彼に、C ++ガイドラインは、コンパイラーがコンパイル時にエラーを送信するようにチョークで書かれていると言いました。

同じ理由を教えてください

4

4 に答える 4

9

簡単な答えのトリッキーな質問-に仮想コンストラクターがないC++ため。


ISO規格では、ISO / IEC 14882:2003およびISO / IEC 14882:2011、12.1コンストラクター、ポイント4:

コンストラクターは仮想(10.3)または静的(9.4)であってはなりません。コンストラクターは、const、volatile、またはconstvolatileオブジェクトに対して呼び出すことができます。コンストラクターは、const、volatile、またはconst volatile(9.3.2)として宣言してはなりません。constおよびvolatileセマンティクス(7.1.5.1)は、構築中のオブジェクトには適用されません。このようなセマンティクスは、最も派生したオブジェクト(1.8)のコンストラクターが終了したときにのみ有効になります。

そして、これはコンパイル時にキャッチできます。

于 2012-08-29T12:14:23.793 に答える
5

コンパイル時エラーが実行時エラーではないのはなぜですか?

実行時に例外シナリオが発生すると、実行時エラーが発生します。コンパイル時エラーは、コンパイラが特定の構造が有効なC++構造としてC++標準で許可されていないことを検出したときに発生します。
C ++標準では、コンストラクターをとしてマークすることはできませんvirtual。したがって、コンパイラはそれを言語文法規則の違反として検出し、エラーにフラグを立てます。

仮想コンストラクタがC++で許可されていない理由に答えるために。
Bjarneは、よくある質問のページでQに次のように答えています。

仮想呼び出しは、部分的な情報が与えられたときに作業を実行するためのメカニズムです。特に、「仮想」を使用すると、オブジェクトの正確なタイプではなく、インターフェイスのみを認識している関数を呼び出すことができます。オブジェクトを作成するには、完全な情報が必要です。特に、作成したいものの正確なタイプを知る必要があります。したがって、「コンストラクターの呼び出し」を仮想化することはできません。

于 2012-08-29T12:18:18.623 に答える
3

仮想コンストラクターを持つことは意味がないため、言語の規則では許可されていません。このコンストラクターはどのように呼び出されますか?特定の基本クラスのさまざまな派生インスタンスを構築するためのC++の一般的なアプローチは、ファクトリメソッドです。

#include <memory>

// the parameters determine the derived type to be instantiated.
std::unique_ptr<IFoo> fooFactory(some parameters);

スマートポインターの選択は、所有権ポリシーによって決定される必要があります。この例では、一意の所有権を使用しています。

于 2012-08-29T12:18:30.197 に答える
-1

C ++では、「仮想」とは、実行時にオブジェクトの有効なクラスに依存し、変数のタイプだけに依存しないことを意味します。

「仮想」コンストラクターは、オブジェクトがまだない(オブジェクトを作成する)ため、決定に依存するクラスがないため、実際には意味がありません。

「仮想コンストラクター」では、C ++で意図されているのは、正確なクラスを知らなくてもオブジェクトを作成できるパターンである場合があります...例:

class Document {
    public:
        static Document *create(...);
    private:
        Document(...);
};

...

// Just use Document::create instead of new Document
std::unique_ptr<Document> p = Document::create(...);

この場合、クラスのユーザーはコンストラクター(プライベート)を呼び出すことはできませんが、パブリックでインスタンスへのポインターを返す静的メソッドのみを呼び出すことができます。構造自体はこの関数によって処理され、返されるオブジェクトは必ずしもDocumentインスタンスではありませんが、あなたが知らない、公開されていない、派生したクラスのインスタンスです。Documentこれにより、たとえば、環境またはへの呼び出しで指定されたパラメータに応じて、実行時に正確なクラスを決定できますcreate

呼び出されるコンストラクターは実行時に決定されるため、これは「仮想コンストラクター」と呼ばれます。ただし、C ++での仮想ディスパッチはインスタンスのクラスにのみ依存するため、C ++での仮想メソッド呼び出しと同じではありません(ただし、前述のように、オブジェクトがまだ存在しないため、コンストラクターには意味がありません。そのため、できません。実際のクラスに応じて決定します)。

于 2012-08-29T12:20:27.953 に答える