gpt4 book ai didi

c++ - 容器类和继承调用虚方法

转载 作者:行者123 更新时间:2023-11-28 05:43:32 25 4
gpt4 key购买 nike

我确定我遗漏了什么,但我真的无法在互联网上找到任何我的代码无法按预期工作的原因:

#include <stdio.h>
#include <iostream>
#include <fstream>
#include "string.h"
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
using namespace std;

class Animal {
private:
char *name;
protected:
enum { tele, empty } bendo;
public:
Animal() {};
Animal(const char *kname) : bendo(empty) {
name = new char[strlen(kname) + 1];
strcpy(name, kname);

}
const char *getname() { return name; }

virtual ~Animal() {
cout << "~" << name << endl;
delete[] name;

}

virtual void print(std::ostream& os) const {
os << "Animal.print" << std::endl;
}

};

class Monkey : public Animal {
protected:
static const char* SOUND;
public:
Monkey(const char *kname) : Animal(kname) { }

~Monkey() { cout << SOUND << SOUND << " "; }

virtual void print(std::ostream& os) const {
os << "Monkey.print" << std::endl;
}
};

const char* Monkey::SOUND = "Mak";

class Tiger : public Animal {
public:
Tiger(const char *kname) : Animal(kname) { }

virtual void print(std::ostream& os) const {
os << "Tiger.print" << std::endl;
}

};

class Cage{
Animal* animals;
unsigned int num;
public:
Cage(){};
~Cage();
void add(const Animal* a) {
Animal* tmp = new Animal[num + 1];
for (unsigned int i = 0; i < num; i++)
tmp[i] = animals[i];
tmp[num++] = *a;
cout << "param: ";
a->print(std::cout);
cout << "in cage: ";
tmp[num - 1].print(std::cout);
animals = tmp;
}
void print(std::ostream& os) {
for (unsigned int i = 0; i < num; i++){
animals[i].print(os);
}
}

};


int main() {
Animal *animal = new Animal("Animal");
Animal *cicus = new Tiger("Cicus");
Animal *csita = new Monkey("Csita");
Animal *tarzan = new Monkey("AIAIAIAI");

Cage* cage = new Cage;
cout << "add animal" << endl;
cage->add(animal);
cout << endl << "add cicus" << endl;
cage->add(cicus);
cout << endl << "add csita" << endl;
cage->add(csita);
cout << endl << "add tarzan" << endl;
cage->add(tarzan);

cout << endl << "cage->print(cout);" << endl;
cage->print(cout);
cin.get();

}

基本上,我想在这里做什么:

  1. 我有一个存储动物的类 (Cage)。
  2. 每只动物都有一个 print(...) 方法。
  3. 如果我调用 cage.print(...),我希望它调用所有动物的 print(...) 方法(Monkey.print(...)、Tiger.print(.. .), 等等),但它总是调用 Animal.print(...) 方法。对于此代码,这是输出:

    add animal
    param: Animal.print
    in cage: Animal.print

    add cicus
    param: Tiger.print
    in cage: Animal.print

    add csita
    param: Monkey.print
    in cage: Animal.print

    add tarzan
    param: Monkey.print
    in cage: Animal.print

    cage->print(cout);
    Animal.print
    Animal.print
    Animal.print
    Animal.print

我在这里错过了什么?我做错了什么?


解决方案
好吧,正如@rodrigo 所说,我遇到了所谓的“对象切片”错误,为了避免这种情况,我不得不将 Animal* animals 替换为 Animal** animals ,所以我存储的不是 Animal 对象,而是 Animal POINTERS。我只是在这里复制代码的重要部分,所以它只显示了这个特定问题的解决方案,所以要小心,它遗漏了其他东西(比如内存处理!)。

class Cage{
Animal** animals; // We need to store pointers!
unsigned int num;
unsigned int max;
public:
Cage(){
num = 0;
max = 10;
animals = new Animal*[max];
};

void add(Animal* a) {
/* Here I just 'optimized' a bit,
but of course the best would be to use linked list. */
if (num == max) {
max*=2;
Animal** tmp = new Animal*[max];
for (unsigned int i = 0; i < num; i++) {
tmp[i] = animals[i];
}
animals = tmp;
}
animals[num++] = a;
}
}

最佳答案

问题是您的 animals 变量是一个 Animal 数组,您需要一个指针或引用才能具有多态行为。

您不能构建一个引用数组,因此您需要一个指针数组:Animal **animals

例如,当您将 Monkey 复制到 Animal 中时,您实际上所做的是复制对象的动物部分并丢失猴子部分。这称为拼接,几乎总是要避免的。

PS:你应该使用 std::stringstd::vector 而不是管理你自己的内存。

关于c++ - 容器类和继承调用虚方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36666774/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com