2016-01-30 33 views
-1

我有一个Animal的数组。C++:多态:调用超级函数

默认情况下,Animal表示"Animal"

我也有Cat,它扩展了Animal并且改为"Meow"

我也有Dog,它延伸Animal并且说"Woof"代替。

我想要什么:

Animal* a[2]; 
a[0] = new Cat(); 
a[1] = new Dog(); 
a[0]->talk(); //Meow 
a[1]->talk(); //Woof 

会发生什么:

Animal* a[2]; 
a[0] = new Cat(); 
a[1] = new Dog(); 
a[0]->talk(); //Animal 
a[1]->talk(); //Animal 

//头

class Animal { 
public: 
    Animal(); 
    ~Animal(); 
    int talk() {return 0;} 
}; 

class Cat : public Animal { 
public: 
    Cat(); 
    ~Cat(); 
    int talk() {return 1;} 
}; 

class Dog : public Animal { 
public: 
    Dog(); 
    ~Dog(); 
    int talk() {return 2;} 
}; 

//.cpp

void letsHear(Animal *a) { 
    _LOG_INFO() << a->talk(); 
} 

int main(){ 
    Animal* a[2]; 
    a[0] = (Animal *)new Cat(); 
    a[1] = (Animal *)new Dog(); 

    letsHear((Animal *)new Cat()); //0 
    letsHear((Animal *)new Dog()); //0 
    letsHear(new Animal()); //0 
    letsHear(a[0]); //0 
    letsHear(a[1]); //0 
    return 0; 
} 
Cat::Cat() {} 
Cat::~Cat(){} 
Dog::Dog() {} 
Dog::~Dog() {} 
Animal::Animal() {} 
Animal::~Animal() {} 
+1

这不是合法的C++。 – Puppy

+0

所以指针现在可以使用'.'?你有没有试过'a [1] - > talk();' – dtech

+0

我刚修好'.'。 – RainingChain

回答

1

您必须声明您的基本方法talk()virtual函数。 看看这个例子。

class Animal { 
public: 
    virtual void talk() { 
     cout << "Animal" << endl; 
    } 
}; 

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

class Dog : public Animal { 
public: 
    void talk() { 
     cout << "Woof" << endl; 
    } 
}; 

然后,你可以调用你的方法,如你的例子。

Animal *a[2]; 
a[0] = new Cat(); 
a[1] = new Dog(); 
a[0]->talk(); //Meow 
a[1]->talk(); //Woof 
3

为了获得在C++中多态行为,则必须声明功能virtual。这是一个好主意,使析构函数虚也处于任何多的基类:

class Animal { 
public: 
    Animal(); 
    virtual ~Animal(); 
    virtual int talk() {return 0;} 
}; 
1

你想要什么叫做dynamic dispatch,就是选择功能在运行时动态调用,基于对象的,其成员之一的类型你想打电话的功能。

在C++中,这是通过使用virtual member functions来完成的。要使用它们,在你的基类中声明相应的成员函数virtual

#include <iostream> 
#include <array> 
#include <memory> 
using namespace std; 

struct Animal { 
    virtual void speak() const { 
     cout << "Animal" << endl; 
    } 
    virtual ~Animal() {} // Better add this, too! 
}; 
struct Cat : public Animal { 
    virtual void speak() const override { 
     cout << "Meow" << endl; 
    } 
}; 
struct Dog : public Animal { 
    virtual void speak() const override { 
     cout << "Wuff" << endl; 
    } 
}; 

int main() { 
    array<unique_ptr<Animal>, 3> animals; 
    animals[0] = make_unique<Cat>(); 
    animals[1] = make_unique<Dog>(); 
    animals[2] = make_unique<Animal>(); 
    for (auto const & a : animals) { 
     a->speak(); 
    } 
    return 0; 
} 

(Live example)

如果(任何)您的派生类添加成员字段,这些类的任何实例的所有权在一些指向基本类型的指针(如我的例子)中,那么你应该遵循aschelper的建议,并使基础破坏者virtual。否则,你会得到内存泄漏。

你可以看到,我使用标准库中的一些概念,我的代码一样unique_ptrarray以及在for循环类型推断。使用这些应该在适当的时候完成,在大多数情况下使用原始数组/指针不再是必要的,并且容易导致内存管理错误。