C ++调用覆盖函数导致调用基函数

时间:2016-04-20 16:03:29

标签: c++

我是C ++的新手,因为我从Java / C#转换。有人可以解释为什么我的代码没有像我认为的那样工作。我有一个简单的Animal类层次结构,然后由Dog和Cat继承。类之间的唯一区别是它们的虚方法toString()/,它显然根据/上调用的类返回一个字符串。好的,所以我输入信息并用cin创建类并将它们推送到动物矢量中。但是当我试图调用它们的toString()时,我得到了基于toString()的结果,而不是覆盖它的结果。这是以下代码:

#include <iostream>
#include <vector>
#include "animal.h"
#include "cat.h"
#include "dog.h"

using namespace std;

int main()
{
    vector<Animal> animals;

    string type;
    string name;
    int age;
    int weight;

    while(cin >> type){
        cin >> name >> age >> weight;
        if(type == "dog"){
            animals.push_back(Dog(name, age, weight);
        }

        else {
            animals.push_back(Cat(name, age, weight);
        }
    }

    for(vector<Animal>::iterator iter = animals.begin(); iter != animals.end();
        iter++){
            cout << iter -> toString() << endl;
        }

    return 0;
}

但是在我做了一些谷歌搜索后,我发现了一个建议,我应该使用指针,因为有一些叫做对象切片的东西。那么我的代码变成了这个:

#include <iostream>
#include <vector>
#include "animal.h"
#include "cat.h"
#include "dog.h"

using namespace std;

int main()
{
    vector<Animal*> animals;

    string type;
    string name;
    int age;
    int weight;

    while(cin >> type){
        cin >> name >> age >> weight;
        if(type == "dog"){
            Dog tempDog(name, age, weight);
            animals.push_back(&tempDog);
        }

        else {
            Cat tempCat(name, age, weight);
            animals.push_back(&tempCat);
        }
    }

    for(vector<Animal*>::iterator iter = animals.begin(); iter != animals.end();
        iter++){
            cout << iter -> toString() << endl;
        }

    return 0;
}

现在我收到编译错误,建议我应该使用&#39; - &gt;&#39;;

我在这里也是一个问题,我想问一下。有没有办法覆盖.cpp文件中的虚方法,而不是定义类的头文件。我最近在c ++中进入了oop,我的想法是在头文件中我只定义了类成员的原型,并在不同的.cpp文件中执行。

1 个答案:

答案 0 :(得分:0)

cout << iter -> toString() << endl;

尝试调用*iter类型的成员函数。由于*iterAnimal*,因此它没有任何成员函数。你需要做的是获取迭代器的值,然后用->调用它的成员函数,如

cout << (*iter)->toString() << endl;

另请注意,如果您可以访问C ++ 11或更高版本,则可以使用基于范围的for循环,例如

for (auto& e : animals)
    cout << e->toString() << "\n";

我也更改为"\n"而不是endl,因为通常您不需要调用flush,因此您只应在知道自己需要时才这样做。

您的代码中也有未定义的行为。

if(type == "dog"){
    Dog tempDog(name, age, weight);
    animals.push_back(&tempDog);
}

是要在向量中添加指向自动对象的指针。当你离开if块时自动对象被自动销毁。在它被销毁之后,你现在有一个指向不再存在的对象的指针。快速解决方法是使用new动态分配对象,如

if(type == "dog"){
    Dog* tempDog = new Dog(name, age, weight);
    animals.push_back(tempDog);
}

现在向量中的指针仍然有效。不幸的是,现在你需要记住在完成它们之后删除所有这些指针。您无需进行手动内存管理,而是可以使用std::unique_ptrstd::shared_ptr等智能指针来管理内存。