重载基类>>运算符
Overloading >> operator for a base class
所以我有一个基类Animal,它继承了两个类,分别是cat和dog。这两个类都重新定义了一个纯虚拟方法,它只把猫的"喵"和狗的"汪汪"计数。在我的main函数中,我希望能够做这样的事情:
int main (void) {
Animal a;
dog d;
while (cin >> a) //is this even possible? would it be cin >> d; instead?
cout << a << endl;
return(0);
}
所以这应该算动物说话的功能,但我怎么做呢?另外,我很困惑,如果你不知道动物的类型,那么你怎么能确定使用哪个说话函数,你会使用模板类吗?
在基类中这样做:
#include <istream>
using namespace std;
class Animal
{
friend istream & operator >> ( istream &is, Animal &animal )
{
animal.readFromStream(is);
return is;
};
protected:
virtual void readFromStream( istream &is ) = 0;
};
和派生:
class Dog : public Animal
{
protected:
virtual void readFromStream( istream &is )
{
// read dog
};
};
下面是重写operator<<
的示例,它调用公共成员函数speak()
。如果您需要访问重载operator<<
中的私有成员,请将其设置为friend
。
#include <iostream>
class Animal {
public:
virtual std::string speak(void) = 0;
};
class Dog : public Animal {
std::string speak() { return "woof"; }
};
class Cat : public Animal {
std::string speak() { return "meow"; }
};
std::ostream& operator<<(std::ostream& out, Animal& a) {
out << a.speak();
return out;
}
int main (void) {
Dog d;
Cat c;
Animal &a = d;
std::cout << a << std::endl;
Animal &a2 = c;
std::cout << a2 << std::endl;
return 0;
}
您应该能够找出如何为operator>>
做类似的事情。
还有,我很困惑,如果你不知道动物的类型,那么你怎么能确定使用哪个说话函数,你会使用模板类吗?
这就是动态绑定/多态性背后的思想。a
和a2
是对Animal
的派生类型的引用,由于speak()
是虚的,因此v-table将包含指向Dog
或Cat
对象所需的speak()
函数的指针。
你不能完全按照自己的想法去做。也就是说,你不能
Animal a;
std::cin >> a;
并期望'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;
}
}
的输入是更复杂的,我不知道你是否可以直接与 所以你可以调用 编辑1 忘记调用 编辑2 应用于OP示例friend ostream &operator<<(ostream &output, const Animal & animal) //output
{
return output << animal.speak();
}
Animal
但是你可以创建一个AnimalLoader
class AnimalLoader {
Animal* _animal;
public:
AnimalLoader() : _animal(NULL) { }
~AnimalLoader() { if(_animal) delete _animal; }
Animal *GetAnimal()
{
Animal *retval = _animal;
_animal = NULL;
return retval;
}
friend istream & operator >> ( istream &input, AnimalLoader &animalLoader )
{
if(_animal) delete _animal;
std::string animalStr;
input >> animalStr;
if(animalStr == "dog")
_animal = new Dog();
else if(animalStr == "cat")
_animal = new Cat();
else
_animal = NULL;
return input;
}
};
int main (void) {
AnimalLoader animalLoader;
while (cin >> animalLoader) {
Animal *animal = animalLoader.GetAnimal();
if(animal != NULL) {
cout << *animal << endl;
delete animal;
}
else {
cout << "ERROR: Could not read Animal." << endl;
}
}
return(0);
}
speak()
- 为什么比较运算符如此快速
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 增量运算符与后缀混淆
- 一个关于在C++中重载布尔运算符的问题
- 运算符C++ "delete []"仅删除 2 个前值
- 模板类无法识别友元运算符
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 关闭||运算符优化
- 通过继承类使用来自不同命名空间的运算符
- C++Cast运算符过载
- 如何使用AngelScript注册SFML Vector2运算符
- 重载元组索引运算符-C++
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 布尔比较运算符是如何在C++中工作的
- 重载运算符new[]的行为取决于析构函数
- 是否需要使用 - &gt;运算符在C 中调用成员函数时