C++ &引用;多态性;非成员函数/运算符,是否需要额外重载?
我想重写父类重载运算符,但我想避免为继承的类重写所有非成员运算符的样板代码。有可能吗 在下面的示例中,我重载了C++ &引用;多态性;非成员函数/运算符,是否需要额外重载?,c++,c++11,polymorphism,operator-overloading,C++,C++11,Polymorphism,Operator Overloading,我想重写父类重载运算符,但我想避免为继承的类重写所有非成员运算符的样板代码。有可能吗 在下面的示例中,我重载了virtualfoo&Foo::operator+=(Foo-const&),并基于一个自由函数Foo&operator+(Foo,Foo-const&)。在Bar中,我覆盖了Bar&Bar::operator+=(Foo const&)覆盖。我想要的是,当我声明Bar+Foo时,free函数调用覆盖函数,并且我希望结果是Foo。我知道重载再次Bar操作符+(Bar,Foo const&
virtualfoo&Foo::operator+=(Foo-const&)
,并基于一个自由函数Foo&operator+(Foo,Foo-const&)
。在Bar中,我覆盖了Bar&Bar::operator+=(Foo const&)覆盖
。我想要的是,当我声明Bar+Foo
时,free函数调用覆盖函数,并且我希望结果是Foo
。我知道重载再次Bar操作符+(Bar,Foo const&)
可以解决这种特殊情况,但如果可能的话,我希望避免显式地这样做(考虑所有其他操作符)。然后还有Foo+Bar
,我想返回Bar
#include <iostream>
class Foo {
public:
Foo(unsigned int bottles=11) : bottles(bottles) {} // This is odd on purpose
virtual void display(std::ostream & out) const {
out << bottles << " bottles";
}
virtual Foo & operator+=(Foo const &);
protected:
unsigned int bottles;
};
std::ostream & operator<<(std::ostream & out, Foo const & f) {
f.display(out);
return out;
}
Foo & Foo::operator+=(Foo const &f) {
bottles += f.bottles;
return *this;
}
Foo const operator+(Foo f, Foo const & g) {
return f += g;
}
class Bar : public Foo {
public:
Bar(unsigned int bottles=0) : Foo(bottles) { enforce(); }
Bar(Foo const & f) : Foo(f) { enforce(); }
void display(std::ostream & out) const override {
out << bottles << " manageable bottles";
}
Bar & operator+=(Foo const &) override;
private:
void enforce() { bottles /= 2; bottles *=2; }
};
Bar & Bar::operator+=(Foo const &f) {
Foo::operator+=(f);
enforce();
return *this;
}
int main () {
std::cout << "----- Foo + Foo -----" << std::endl;
Foo bar;
Foo becue(2);
std::cout << bar << " + " << becue << " -> (+) "
<< bar + becue << std::endl;
std::cout << "----- Bar + Bar -----" << std::endl;
Bar crazy(bar);
Bar horse(5);
std::cout << crazy << " + " << horse << " -> (+) "
<< crazy + horse << std::endl;
std::cout << "----- Bar + Foo -----" << std::endl;
std::cout << crazy << " + " << bar << " -> (+) "
<< crazy + bar << std::endl;
std::cout << "----- Foo + Bar -----" << std::endl;
std::cout << bar << " + " << horse << " -> (+) "
<< bar + horse << std::endl;
return 0;
}
#包括
福班{
公众:
Foo(unsigned int瓶=11):瓶(瓶){}//这是故意的
虚拟空间显示(标准::ostream&out)常数{
out问题源于调用时发生的对象切片
Foo const operator+(Foo f, Foo const & g) {
return f += g;
}
这里,f
通过值传递,这意味着Foo
子类型的任何附加信息都将被丢弃。因此编译器只看到Foo
,无法调用多态运算符
为了防止切片,您必须传递指针或引用,但这意味着您需要一个l值
作为第一个操作数,并且不能使用const
,因为您正在对其调用运算符+=
所以你本来可以
Foo const operator+(Foo& f, Foo const & g) {
return f += g;
}
它适用于您的具体情况,如:
Foo bar;
Bar crazy(bar);
std::cout << crazy + bar << std::endl;
Foo-bar;
疯狂酒吧;
std::我是否可以建议添加另一个子类型的Foo
。称之为Baz
。然后,制定出+=
操作符的LHS和RHS的所有组合应该发生什么的策略。我有一种感觉,这将使您的思维更加清晰。问题之一是您将操作符+和操作符+混合在一起r+=。因此(我猜想)您使用了副本作为+运算符的参数,以避免在确实需要常量引用以使多态性工作时对它们进行修改。但是您不能使用,因为+=只接受非常量引用,因为它修改了对象。模板t运算符+(t,const Foo&f){return t+=f;}
?但请注意不要为此层次结构定义任何非模板运算符。@ChrisR。事实上,operator+
委托给operator+=
在two@greendiod好的,但不是当你想让多态性工作并且保持你的l值不变的时候,我也想到了t对象切片,但我离开了f
,因为我已经尝试了Foo const&f
,当然你是对的,它甚至不会编译。除非我在return Foo(f)+=g;
中使用一个临时的like。使用这种方法,现在我又回到了原点(工作切片).不幸的是,如果我像你建议的那样通过引用传递f
,我会得到非常奇怪的结果!或者我可以使用虚拟构造函数?