Вы не можете делать именно то, что вы хотите.То есть вы не можете
Animal a;
std::cin >> a;
и ожидать, что тип «а» изменится.По сути, объекты не являются полиморфными - указатели и ссылки полиморфны.
Зная это, вы можете сделать что-то почти то, что вы хотите:
Animal* pA;
std::cin >> pA;
std::cout << *pA << "\n";
delete pA;
Вы можетеВыполните это путем перегрузки
istream& operator>>(istream&, Animal*&);
для создания (через new
) объекта указанного во время выполнения типа.
Рассмотрим эту программу:
#include <iostream>
class Animal {
public:
virtual void speak(std::ostream& os) const = 0;
virtual ~Animal() {} // must be virtual
};
class Dog : public Animal {
public:
void speak(std::ostream& os) const { os << "woof"; }
};
class Cat : public Animal {
public:
void speak(std::ostream& os) const { os << "meow"; }
};
std::ostream& operator<<(std::ostream& os, const Animal& being) {
being.speak(os);
return os;
}
std::istream& operator>>(std::istream& is, Animal*& zygote) {
std::string species;
is >> species;
// fetch remainder of line with std::getline()
if(species == "cat") {
// parse remainder of line
// Finally, create a Cat
zygote = new Cat;
return is;
}
if(species == "dog") {
// parse remainder of line
// and create a Dog
zygote = new Dog;
return is;
}
// Hmm, unknown species? Probably not safe to create
std::cerr << "Warning! Unknown species. Could be dangerous!\n";
is.setstate(std::ios::failbit);
zygote = 0;
return is;
}
int main () {
Animal *pPet;
while(std::cin >> pPet) {
std::cout << *pPet << "\n";
delete pPet;
}
}