1

以前に、これが悪いと考えられる理由を尋ねました。

class Example
{
 public: 
  Example(void);
  ~Example(void);
  void f() {}
}

int main(void)
{
 Example ex(); // <<<<<< what is it called to call it like this?

 return(0);
}

これで、タイプ Example を返す代わりに関数プロトタイプを作成していることがわかります。ただし、g ++およびMS VC ++で機能する理由はまだわかりません。

私の次の質問は、上記を使用することです。この呼び出しは有効ですか?

int main(void)
{
 Example *e = new Example();

 return(0);
}

? それと単純に Example e() を呼び出すことの違いは何ですか??? 私が知っているように、それは関数プロトタイプですが、一部のコンパイラはそれを許し、デフォルトのコンストラクターを呼び出すことを許可しているようです? 私もこれを試しました:

class Example
{
 private:
  Example();

 public:
  ~Example();
};

int main(void)
{
 Example e1(); // this works
 Example *e1 = new Example(); // this doesn't

 return(0);
}

だから私は少し混乱しています:(これが何百万回も聞かれたらごめんなさい。

4

5 に答える 5

5

簡単だよ、ダニエル:

Example *e = new Example();

「Example」という関数に見えませんよね?関数には、戻り値、名前、およびパラメーターがあります。上記はどのように適合しますか?

例 e1(); //これは機能します

ええ、どこにもインスタンスを作成しないためですExample。周囲の名前空間のどこかに関数が定義されていることをコードに伝えるだけで、おそらくその関数を呼び出すことができます。はい、確かに Example のオブジェクトを返すためにインスタンスが作成されます。しかし、それはインスタンスがその時点で作成されるという意味ではありません。むしろ、関数を呼び出すと、関数内でインスタンスが作成されます。

于 2009-01-19T14:28:20.413 に答える
1

この質問は、この動作を理解するのに役立ちます

于 2009-01-19T14:27:48.307 に答える
1

うーん...OKこれ:

例 e1();

うまくいきません。あると思うか、一部のコンパイラがそれを受け入れていると思うかもしれませんが、e1 という Example のインスタンスを作成せず、関数プロトタイプを宣言するだけです。ブラケットを削除すると、必要なことが行われます。

これ:

Example* e1 = new Example();

コンストラクターがプライベートであるため、機能しません。コンストラクターを public にすると、ヒープ上にオブジェクトが作成され、e1 はそのオブジェクトへのポインターになります。作業が完了したら、オブジェクトを削除する必要があります。

于 2009-01-19T14:28:24.110 に答える
1

最初の質問では、「new Example()」は有効でしょうか。はい、これは完全に正当な C++ コードです。完全に正しくするには、main() から戻る前にオブジェクトを削除する必要があります。そうしないと、メモリ リークが発生します。

例:

int main(void)
{
 Example *e = new Example();
 delete e;
 return(0);
}

最後の質問です。「例 e1();」の行 関数プロトタイプを宣言しているため有効です。これにより、実際にはマシンコードが実行されるわけではありません (おそらくスタックスペース)。これは単純に、引数のない関数プロトタイプがあり、型の Example を返す、ということです。

ただし、2行目は間違いなく失敗します。この時点で、実際に Example のコンストラクターを実行しようとしています。関数のアクセシビリティは非公開であるため、これは合法的ではなく、コンパイラ エラーが発生します。

于 2009-01-19T14:28:47.570 に答える
0

「これは解析する」、「これはコンパイルする」、「このリンクは」、「これは機能する」を区別し、C++ パーサー/コンパイラ/リンカーのように考えてみて、最初の例が

Example e1(); // function prototype

関数宣言のようです。パーサーはこのようにそれを理解するので、たとえば のメンバー関数を呼び出すことはできませんe1。コンパイラは関数を参照するシンボルを生成しますが (まだ表示されていません)、その関数はどこにも使用されていないため、エラーは発生しません。このコードを追加すると、次のようになります。

e1.f();// since e1 is a function, it has no member 'f' => compiler error

(補足として: このコードもコンパイルされます:

int a_function_prototype(int); // another prototype.
e1(); // should work!
a_function_prototype(5);

ただし、コンパイラが終了すると、リンカーは実際の関数本体を探し始めますが、何も見つかりません。)

今ライン以来

Example* e = new Example();

コンパイラが認識するキーワードnew が含まれており、それが新しいオブジェクトの割り当てと構築でのみ見つかることがわかっている場合、そのためのコードを生成します。

于 2009-01-19T14:38:00.813 に答える