4

次のことを考慮してください。

class Abstract
{
public:
    virtual void func() = 0;
};

int main() {

    Abstract abs1; // doesn't compile
    Abstract * abs2 = new Abstract(); // doesn't compile
    Abstract * abs3;  // compiles

    return 0;
}

を実装していないことに注意してくださいfunc()。では、なぜAbstract * abs3; 純粋仮想メソッドと抽象クラスがあるところで実行できるのでしょうか? abs3->func(); を実行しようとすると実行時エラーが発生することはわかっています。、しかし、それでも、なぜ C++ がそのコードのコンパイルを許可するのか、私には明らかではありません ...?

ありがとう、ロン

4

6 に答える 6

7

abs3クラスへのポインタです。Abstractの具体的なサブクラス、またはNULLに安全に初期化できます。抽象クラスを作成することはできませんが、それらへのポインターを作成できる必要があるため、コンパイラーはそれを許可する必要があります。例については、以下を参照してください

class Concrete: public Abstract
{
public:
    virtual void func() { // do something };
};


int main ()
{
   Abstract* abs3 = NULL;
   abs3 = new Concrete;
}
于 2011-09-01T10:53:39.333 に答える
4

抽象クラスをインスタンス化することはできませんが、それへのポインタを持つことはまったく問題ありません。これは実際、OO 設計で非常によく使用されます。

于 2011-09-01T10:44:55.677 に答える
3

簡潔な答え

抽象クラスへのポインタを作成しても問題ないため、コンパイラはエラーを発行しません。

長い答え

クラスをインスタンス化し、型のオブジェクトを作成するために、コンパイラはその型の構成を知る必要があります。

システム上のすべてのポインターは、それらが指す型に関係なく同じサイズであるため、Abstract クラスへのポインターを作成できます。
ポインターを作成してもコンストラクターは呼び出されないことに注意してください。

クラスには完全に定義されていないメソッドがあり、コンパイラはクラスの構成を認識していないため、Abstract クラスのオブジェクトを作成できません。したがって、インスタンス化を禁止します。

編集:
純粋な仮想関数に定義を提供しても(それを行うことは完全に有効です)、関数を純粋な仮想として宣言した瞬間に、コンパイラはクラスを抽象(不完全)として扱うため、抽象クラスをインスタンス化することはできません。これ以上インスタンス化することはできません。

于 2011-09-01T10:44:11.163 に答える
1

実際、抽象クラスへのポインターを作成する可能性があることのポイントは、抽象クラスから派生した(具体的な)クラスを指すことです。

class Abstract
{
public:
    virtual void func() = 0;
};

class Derived1 : public Abstract
{
public:
    virtual void func() { /* do something */ }
}

class Derived2 : public Abstract
{
public:
    virtual void func() { /* do something else */ }
}

そして、例えば:

Abstract * ap;

if (/*something*/)
    ap = new Derived1();
else
    ap = new Derived2();

ap->func();
delete ap;
于 2011-09-01T10:52:12.423 に答える
1

継承はあなたが見逃している重要なアイデアです。Vehicleが抽象で、aCarがビークルの場合、はVehicle*インスタンス化されたへのポインタに対して完全に有効な型ですCar。抽象基本クラスは、メソッド(参照)への引数として有効な型であり、aCarまたはaBikeが渡されたかどうかに関係なく、の正しい仮想実装funcが呼び出されます。それは言語の重要な特徴です。

于 2011-09-01T10:53:13.400 に答える
0

1 つ以上のメソッドが実装されていないクラスのインスタンスを持つことはできません。

ここでやろうとしているのは、 という名前の純粋な抽象メソッドを持つクラスのインスタンスを持つことですfunc(): これは不可能です.

Abstract * abs3

コンパイルが初期化されていないポインタである場合、のインスタンスを割り当てていませんAbstract

Abstract abs1;
Abstract * abs2 = new Abstract();

決してコンパイルされません。Abstract実装を提供することを (継承によって)指定する必要がfunc()あり、その時点で、そのような派生クラスのインスタンスを持つことができます。

于 2011-09-01T11:53:32.933 に答える