web-dev-qa-db-ja.com

関数は抽象基本クラスを引数として受け入れることができますか?

基本的なクラスとカプセル化のアイデアに慣れてきたので、ポリモーフィズムを理解することに着手しましたが、それを機能させる方法がよくわかりません。私が検索した例の多くは、実際には本当に強制されています(クラスFooとBarは抽象的すぎてユーティリティを見ることができません)が、基本的な概念を理解する方法は次のとおりです。基本クラスを作成し、基本メソッドが何であるかを変更する他の多くのものを派生させますdo(ただし、それらが「何であるか」ではありません)、次に、任意のものを受け入れて処理する一般的な関数を作成できます派生クラスは、外観をある程度標準化したためです。その前提で、私は次のように基本的な動物->猫/犬の階層を実装しようとしました:

class Animal {
  public:
    virtual void speak() = 0;
};

class Dog : public Animal {
  public:
    void speak() {cout << "Bark bark!" << endl;}
};

class Cat : public Animal {
  public:
    void speak() {cout << "Meow!" << endl;}
};

void speakTo(Animal animal) {
    animal.speak();
}

talkToが取ることができる場所は、一般的な種類の動物を取り、それを話すことができます。しかし、私が理解しているように、Animalをインスタンス化できないため(特に関数の引数で)、これは機能しません。それでは、私はポリモーフィズムの基本的な有用性を理解していますか、そしてどうすれば私がやろうとしたことを本当に行うことができますか?

20
Connor Glosser

Animalクラスなどのオブジェクトを作成できないため、派生クラス関数にAnimalオブジェクトを渡すことはできません。これは抽象クラ​​スです。
クラスに少なくとも1つの純粋仮想関数(speak())が含まれている場合、そのクラスは抽象クラスになり、そのオブジェクトを作成することはできません。ただし、ポインタまたは参照を作成して渡すことができます。 Animalポインタまたはメソッドへの参照を渡すことができます。

void speakTo(Animal* animal) 
{
    animal->speak();
}

int main()
{
    Animal *ptr = new Dog();
    speakTo(ptr);

    delete ptr;   //Don't Forget to do this whenever you use new()
    return 0;
}
20
Alok Save

コピーの代わりに参照を渡す必要があります。

void speakTo(Animal& animal) {
    animal.speak();
}
11
Vaughn Cato