C++中的多态性永远不会升级

Polymorphism in C++ never upcasts

本文关键字:永远 多态性 C++      更新时间:2023-10-16

我做java开发人员已经很长时间了。我肯定我想错了。

但是我有一个等级动物和一个等级狗。狗延伸了动物,在我的主要,我做了一堆狗,并把它们粘在动物的载体上。

在对它们进行迭代时,我无法访问最初包含Dog的对象上的Dog特定方法。

我做错了什么?

动物

 #include "Header.h"
class Animal {
    std::string name;
    int age;
public:
    std::string getName(){ return name;}
    virtual int getAge(){ return age;}
    virtual int getRealAge();
    Animal(std::string name, int age);
    ~Animal();
};
Animal::Animal(std::string name, int age){
    this->name = name;
    this->age = age;
}
int Animal::getRealAge() {
    return this->age*100/2;
}
Animal::~Animal() {
}

#include "Header.h"
class Dog : public Animal {
public :
    Dog(std::string name, int age);
    ~Dog();
    int getAge();
};
Dog::Dog(std::string name, int age) : Animal::Animal(name, age) {
}
Dog::~Dog(){
}
int Dog::getAge() {
    return Animal::getAge()*7;
}

#include "Header.h"
using namespace std;
int main() {
    cout << "Hello, World!" << endl;
    // I make a bunch of Dogs
    Dog tmp0("Ellie", 1);
    Dog tmp5("sam", 2);
    Dog tmp4("lindsay", 3);
    Dog tmp3("shilo", 4);
    Dog tmp2("rex", 5);
    Dog tmp1("bob", 6);
    Animal tmp00("nick", 11);
    vector<Animal*> animals;
    animals.push_back(&tmp0); // Dog is-an Animal
    animals.push_back(&tmp1);
    animals.push_back(&tmp2);
    animals.push_back(&tmp3);
    animals.push_back(&tmp4);
    animals.push_back(&tmp5);
    animals.push_back(&tmp00); //new
    for(auto &animal : animals){
        Animal *tmp = NULL;
        if (typeid(animal) == typeid(Animal)){
            cout << "Found animal" << endl;
        }else{
            cout << "Found animal" << endl;
            cout << animal->getName() << " is " << animal->getAge() << endl;
        }

    }

    return 0;
};

输出

Found Dog
Ellie is 1
Found Dog
bob is 6
Found Dog
rex is 5
Found Dog
shilo is 4
Found Dog
lindsay is 3
Found Dog
sam is 2
Found Dog
nick is 11

但它们都应该乘以7。

编辑

我将虚拟类型添加到上面Animal类中的方法中,并将Animal类型的Object添加到我的向量中。

但是,在main中的for循环中,对象也以dog类型返回。

您需要使getAge成为一个虚拟函数。

http://en.wikipedia.org/wiki/Virtual_function

我不确定你说的单词in the for loop in the main, the object returns as type dog as well是什么意思。如果你的意思是,typeid(animal) == typeid(Animal)的条件永远不成立,那么它应该如何工作,因为typeid将返回大多数派生的动态对象类型。

我建议您编写一个多态函数,接受最合适的对象,而不是typeid。也就是说,你可以写

void animal_test(Dog& dog)
{
    /* this will be called when argument is Dog or its ancestor… */
}
void animal_test(Animal& any)
{
    /* this will be called in all other cases */
}

至于虚拟函数,这是Java和C++的主要区别,因为在C++中,默认情况下函数不是虚拟的。如果函数不是虚拟的(至少在类层次结构中的某个点上,比用于调用该函数的对象指针更高),那么将调用哪个函数完全取决于指针类型。

将getAge虚拟化是明智的选择,但至少值得注意的是,您可以通过替换。。。

    if (typeid(animal) == typeid(Animal)){
        cout << "Found animal" << endl;
    }else{
        cout << "Found animal" << endl;
        cout << animal->getName() << " is " << animal->getAge() << endl;
    }

具有

    if (Dog* p = dynamic_cast<Dog*>(&animal))
    {
        // inside here, p is known to be a Dog* at compile time, so
        // getAge() is statically dispatched to Dog::getAge
        cout << "Found animal/dog" << endl;
        cout << p->getName() << " is " << p->getAge() << endl;
    }else{
        cout << "Found animal" << endl;
    }

这个dynamic_cast<>在C++中被认为有点反模式(每个使用getAge()的客户端代码站点都必须知道派生类的细节,这太疯狂了),virtual函数是更好的方法。