Массивы и наследование с++
Изучаю с++, столкнулся с проблемой. Есть класс Animals. От него два производных класса Cat и Dog. Как сделать массив из объектов Cat и Dog, чтобы можно было обращаться к ним по индексу массива? При обращении к полю класса вываливается ошибка, что в классе Animals нет поля age (пример в функции main). Его там действительно нет, но и я ведь обращаюсь к производному классу, где это поле присутствует... Заранее спасибо за помощь!
class Animals{
public:
Animals(){}
};
class Cat: public Animals {
public:
int age;
std::string name;
Cat() {
this->age = 0;
this->name = "";
}
};
class Dog: public Animals{
public:
int age;
std::string name;
Dog(int age, std::string name) {
this->age = age;
this->name = name;
}
Dog() {
this->age = 0;
this->name = "";
}
};
int main()
{
Animals anm[10];
anm[0]=Cat();
anm[1]=Dog();
std::cout<<anm[1].age;
}
Ответы (2 шт):
Вообще-то странное решение - почему бы не вынести общее поле age (как и name) в базовый класс?
Тем более что при присваивании
anm[0]=Cat();
происходит срезка, и поля эти остаются "за бортом".
Если позарез требуется такое странное решение - работайте через указатели, с приведением типов. Типа
Animals* anm[10];
anm[0]= new Cat();
anm[1]= new Dog();
std::cout<<((Dog*)anm[1])->age;
Примерно так. Но все это говорит о совершенно непродуманном проектировании...
Я бы ваш простейший пример делал примерно так:
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
class Animal{
public:
Animal(int age = 0, const char * name = ""):age(age),name(name){}
virtual string get_name() const = 0;
protected:
int age;
string name;
};
class Cat: public Animal {
public:
Cat(int age=0, const char* name = ""):Animal(age, name)
{
}
virtual string get_name() const
{
return "Cat " + name;
}
};
class Dog: public Animal {
public:
Dog(int age=0, const char* name = ""):Animal(age, name)
{
}
virtual string get_name() const
{
return "Dog " + name;
}
};
int main()
{
Animal* anm[2];
anm[0] = new Cat(1,"Vaska");
anm[1] = new Dog(2,"Sharik");
cout << anm[0]->get_name() << endl;;
cout << anm[1]->get_name() << endl;;
}
Подход тут может быть самым разнообразным. Если классы ничем не будут отличаться, то можно просто указать тип животного. Для конкретно данного случая, я бы пользовался этим подходом:
enum class Type { cat, dog }; //тип животного(известен при рождении)
class Animals {
public:
Animals(Type t = Type::cat, const unsigned age = 1)
: type(t), age(age), name(t == Type::cat ? "cat " : "dog ") {}
//имя придается после рождения
void set_name(const string& s) { name += s; }
string get_name() const { return name; }
unsigned age;
private:
std::string name = "";
Type type;
};
int main() {
Animals anm[10];
anm[0] = Animals(Type::dog, 5);
anm[0].set_name("sharik");
std::cout << anm[0].get_name() << ' ' << anm[0].age
<< '\n' << anm[1].get_name() << ' ' << anm[1].age;
return 0;
}