C ++中的多态性从不向上转换

时间:2014-09-11 04:03:21

标签: c++

我很长时间以来一直是java开发人员。我确定我认为这是错误的方式。

但我有一类动物和一类狗。狗伸​​展动物,在我的主要部分,我制作一堆狗并将它们粘在动物的矢量中。

在对它们进行迭代时,我无法在最初为狗的对象上访问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类中的方法,并向我的vector添加了一个类型为Animal的Object。

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

3 个答案:

答案 0 :(得分:3)

您需要将getAge设为虚拟功能。

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

答案 1 :(得分:2)

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

而不是typeid我会建议您编写一个多态函数,它将接受最合适的对象。 I. e。你可以写

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 ++函数默认情况下不是虚函数。如果你的函数不是虚函数(至少在类层次结构中的某个点,比用于调用该函数的对象的指针更高),将调用哪个函数仅取决于指针类型。

答案 2 :(得分:1)

让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()的客户端代码网站来说,它必须知道派生类&#39;具体而言,virtual函数是更好的方法。