Могут ли функции принимать абстрактные базовые классы в качестве аргументов? - PullRequest
18 голосов
/ 17 февраля 2012

Освоившись с идеей базовых классов и инкапсуляции, я начал понимать полиморфизм, но не могу понять, как заставить его работать.Многие примеры, которые я искал, выглядят как действительно, действительно принудительно (классы Foo и Bar слишком абстрактны для меня, чтобы я мог увидеть утилиту), но вот как я понимаю основную концепцию: вы пишетебазовый класс, производный от него целый набор других вещей, которые меняют то, что базовые методы делают (но не то, что они «есть»), тогда вы можете написать общие функции для принятия и обработки любого из производныхклассы, потому что вы несколько стандартизировали их внешний вид.Исходя из этой предпосылки, я попытался реализовать базовую иерархию Animal-> cat / dog следующим образом:

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();
}

, где имеется возможность говорить, может взять общее животное и заставить его говорить, ну, в общем, говорить.Но, насколько я понимаю, это не работает, потому что я не могу создать экземпляр Animal (в частности, в аргументе функции).Тогда я спрашиваю, понимаю ли я основную утилиту полиморфизма, и как я могу действительно делать то, что я пытался сделать?

Ответы [ 2 ]

20 голосов
/ 17 февраля 2012

Вы не можете передать объект Animal в производную функцию класса, потому что вы не можете создать объект Animal class и все, это Abstract class .
Если класс содержит хотя бы одну чистую виртуальную функцию (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;
}
11 голосов
/ 17 февраля 2012

Вам нужно будет передать ссылку вместо копии:

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