我正在编写一个涉及多态性的C++程序。我需要重载运算符"<<">和">>">作为友元函数。我有基类base和3个派生类:>der1、der2[/strong>、der3//strong>和一个指向基类*pbr/strong>的指针。如果我将函数声明为
istream &operator>>(istream &i,der1 &d1) {...}
istream &operator>>(istream &i,der2 &d2) {...}
istream &operator>>(istream &i,der3 &d3) {...}
并像一样称呼他们
base *p;
p=new der1;
cin>>p;
程序不会编译,因为没有带有base参数的函数。但如果我这样声明,如果实际对象的类型是der1、der2或>der3[/strong>,则没有任何区别,尽管我希望它根据对象的类型表现不同。我所能想到的就是在base中创建一个虚拟函数,并覆盖它继承的类。但因此,我将不得不将函数称为
*p>>cin
看起来不那么自然。我该如何解决这个问题?
不要试图使operator>>
成为成员。你不能并且仍然将cin
保持在左侧。只要让它成为一个免费函数,并让它调用一个成员(然后可以是虚拟的):
struct base { virtual void read(istream &i); };
istream &operator>>(istream &i,base &b) {b.read(i); return i;}
您可以为基类创建operator>>
istream &operator>>(istream &i, base *b) {
b->ReadFromIstream(i);
return i;
}
然后使ReadFromIstream
成为一个虚拟函数,并从派生类中重载它。通过这种方式,您可以获得相同的语法cin >> p
,并且它们根据p
的类型表现不同。
我认为您对C++运行时的能力有一些幻想:-)。C++运行时无法(或选择不)查看基指针参数是否指向派生多态性取决于"调用对象",而不是参数对象。如果说p->f()
,*p
中的代码将知道调用什么,但在::f(p)
中没有代码内省*p
并决定调用哪个f
。该决定是在编译时基于p
的静态类型做出的。
也就是说,解决方法是@DarkFalcon描述的策略。从函数调用对象的虚拟方法。