3

以下のプログラムは、明らかな理由でコンパイルされません。

#include <iostream>
using namespace std;

class A {
 public:
  A() { pVirt(); }
  virtual void pVirt() const = 0 { count<<"A::pVirt()"; }
};

int main() {
 A aObj;
 aObj.pVirt();
 reutrn 0;
}

質問: 1. シグネチャの「virtual void pVirt() const = 0」の 0 は何を意味しますか?、これは vtable の NULL メモリ オフセットを示していますか、それとも単に構文上の制約を示していますか?

  1. 0 が NULL メモリ オフセットである場合 (そうである場合)、なぜ VC++ が別のメモリ アドレスを指定することを許可しないのか、これが外部コンストラクターから純粋仮想関数を呼び出すことができない理由です (vtable がオブジェクトが完全に構築された後に作成されます。)?
4

4 に答える 4

5

署名「virtualvoidpVirt()const = 0」の0は、何を意味しますか?、

この部分=0pure-specifierと呼ばれます。これにより、仮想関数が純粋になり、クラスが抽象になります。

純粋仮想関数は定義を持っている必要はありません。オプションでクラスの外部に定義を指定することもできますが、非抽象派生クラスで関数をオーバーライドする必要があります。

class A
{
 public:
     virtual ~A() {};
     virtual void f() =0;
};

void A::f() { std::cout << "A::f" << std::endl; } //optional

の定義はfクラスを非抽象化しないため、A:のインスタンスを作成することはできません。

A a; //error - A is abstract

さらに、派生クラスは、A::f抽象化されないようにするためにオーバーライドする必要があります。

class B : public A {};

B b; //error : B is still an abstract class as it didn't override A::f

class C : public A { void f() {} };

C c; //okay : C override A::f

また、派生クラスの実装は、基本クラスの実装を呼び出すことを選択できます。

class D : public A { void f() {  A::f(); } }; //defaults to A::f

D d; //okay : D override A::f, but calls A::f internally

お役に立てば幸いです。

于 2013-02-06T12:23:32.117 に答える
4

関数が純粋仮想であることを示すのは単なる構文です。実際の意味はまったくありません。C ++の設計者は、の代わりに使用pureすることもできます。そうしない唯一の理由は、彼らが新しい予約語を言語に導入したくないということだったと思います(これは、新しく予約された単語を識別子としてすでに使用している既存のコードを壊すためです)。abstract= 0

(このような単語は文脈依存のキーワードになるため、予約する必要はありませんが、文脈依存のキーワードの概念は最近主流になり、この構文ははるかに古いものです。)

于 2013-02-06T12:22:05.470 に答える
2

= 0関数宣言の は単なる構文です。2 つのトークン シーケンスは、関数が純粋であることを意味します。それだけです。また、トークンのいずれかを他のものに置き換えることはできません= 0L。たとえば、合法ではありません。

エラーが発生する理由は、単に構文が許可されていないためです。他に何もないとしても、歴史的な理由からです。純粋仮想関数の定義を提供する場合は、クラスの外で行う必要があります。

また純粋仮想関数の定義を提供すると、コンストラクターから呼び出すことができます。仮想呼び出しメカニズムを無効にするだけです。例えばA::pVirt()。実際の関数呼び出しに動的解決が含まれ、解決の結果が純粋な仮想関数になる場合、関数が定義されているかどうかに関係なく、未定義の動作になります。ここでの動機は、それを定義しないようにすることです。通常、仮想関数は、呼び出すかどうかに関係なく、定義する必要があります。これは、コンパイラがそのアドレスを に配置する必要があり、vtable定義されていない場合、アドレスがないためです。関数を純粋仮想化すると、そのアドレスをvtable. したがって、定義する必要はありません。しかし、vtable を介して関数を呼び出そうとすると、驚くかもしれません。

于 2013-02-06T12:33:24.610 に答える
1

仮想関数の= 0後は、「これは純粋な仮想関数であり、派生関数で実装する必要がある」ことを意味します。あなたの例のように、関数を実装することはまだ可能です。それ自体には他の意味はありません。他の番号、アドレス、その他のものを使用することはできません。でいくつかの機能を持つことができますが=0、それでも同じ意味になります。

于 2013-02-06T12:23:52.297 に答える