获取要继承的函数的函数

时间:2010-06-16 00:08:44

标签: c++ inheritance

假设我有一个基类Animal,一个类Cow继承,一个Barn类包含一个Animal向量,让我们说动物类有虚拟函数scream()Cow覆盖。

使用以下代码:

Animal.h

#ifndef _ANIMAL_H
#define _ANIMAL_H
#include <iostream>
using namespace std;

class Animal {
public:
    Animal() {};
    virtual void scream() {cout << "aaaAAAAAAAAAAGHHHHHHHHHH!!! ahhh..." << endl;}
};

#endif  /* _ANIMAL_H */

Cow.h

#ifndef _COW_H
#define _COW_H

#include "Animal.h"

class Cow: public Animal {
public:
    Cow() {}
    void scream() {cout << "MOOooooOOOOOOOO!!!" << endl;}
};

#endif  /* _COW_H */

Barn.h

#ifndef _BARN_H
#define _BARN_H

#include "Animal.h"
#include <vector>

class Barn {
    std::vector<Animal> animals;

public:
    Barn() {}
    void insertAnimal(Animal animal) {animals.push_back(animal);}
    void tortureAnimals() {
        for(int a = 0; a < animals.size(); a++)
            animals[a].scream();
    }
};

#endif  /* _BARN_H */

最后是main.cpp

#include <stdlib.h>
#include "Barn.h"
#include "Cow.h"
#include "Chicken.h"

/*
 * 
 */
int main(int argc, char** argv) {
    Barn barn;
    barn.insertAnimal(Cow());
    barn.tortureAnimals();
    return (EXIT_SUCCESS);
}

我得到了这个输出:

aaaAAAAAAAAAAGHHHHHHHHHH!!! ahhh...

我应该如何对此进行编码以获取MOOooooOOOOOOOO!!!(以及继承Animal希望scream()的其他类别)?

3 个答案:

答案 0 :(得分:12)

std::vector<Animal>只能包含Animal个对象,而不能包含Cow个对象。

当您说barn.insertAnimal(Cow());

时会发生什么
  1. 通过Cow()
  2. 的评估创建了Cow类型的临时对象
  3. 参数animal是从该临时母牛复制构建的,因为您选择按值传递它。这个animal是临时牛的Animal部分的副本。这称为 object-slicing
  4. 向量中的下一个元素是从参数animal复制构造的。现在你已经有了一头牛和另外两头动物,但你只想要一头牛!
  5. 参数animal已销毁,因为insertBarn返回。
  6. 临时母牛被摧毁,因为评估在行尾已达到分号(更准确地说:完整表达的评估已经完成)。
  7. 这里有什么教训?不要按价值传递动物,也不要按价值存放动物。 运行时多态性需要一个间接级别。您可能需要std::vector<Animal*>std::vector<shared_ptr<Animal> >boost::ptr_vector<Animal>

答案 1 :(得分:2)

存储动物指针的细微修改应该有所帮助:

#ifndef _BARN_H
#define _BARN_H

#include "Animal.h"
#include <vector>

class Barn {
    std::vector<Animal *> animals;

public:
    Barn() {}
    void insertAnimal(Animal *animal) {animals.push_back(animal);}
    void tortureAnimals() {
        for(int a = 0; a < animals.size(); a++)
            animals[a]->scream();
    }
};


int main(int argc, char** argv) {
    Barn barn;
    barn.insertAnimal(new Cow());
    barn.tortureAnimals();

    // should clean up barn contents here...

    return (EXIT_SUCCESS);
}

答案 2 :(得分:2)

您正在进行按值传递,因此Cow正在进入Animal

使用Animal *代替工作,虽然这有内存泄漏:

class Barn {
    std::vector<Animal *> animals;

    void insertAnimal(Animal *animal) {animals.push_back(animal);}

    void tortureAnimals() {
        for(int a = 0; a < animals.size(); a++)
            animals[a]->scream();
    }
};

int main(int argc, char** argv) {
    Barn barn;
    Cow *c = new Cow();
    barn.insertAnimal(c);
    barn.tortureAnimals();
    /* delete them here... */
}