带有继承的 C++ 运算符重载
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17122111/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ operator overloading with inheritance
提问by prongs
Let's say I have a class called Vehicle
and another called Car
that extends Vehicle
class. I want to implement ++
operators for both classes.
假设我有一个名为的类Vehicle
,另一个名为Car
扩展Vehicle
类。我想++
为两个类实现运算符。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <sstream>
#include <typeinfo>
#define debug(args...) // Just strip off all debug tokens
using namespace std;
// CUT begin
#define debug(args...) {dbg,args;cout<<endl;}
struct debugger{template<typename T> debugger& operator ,(const T& v){cout<<v<<" ";return *this;}}dbg;
template <typename T1,typename T2> inline ostream& operator<<(ostream& os,const pair<T1,T2>& p){return os<<"("<<p.first<<", "<<p.second<<")";}
template<typename T>inline ostream&operator<<(ostream& os,const vector<T>& v){string delim="[";for(unsigned int i=0;i < v.size();i++){os<<delim<<v[i];delim=", ";}return os<<"]";}
template<typename T>inline ostream&operator<<(ostream& os,const set<T>& v){string delim="[";for (typename set<T>::const_iterator ii=v.begin();ii!=v.end();++ii){os<<delim<<*ii;delim=", ";}return os<<"]";}
template<typename T1,typename T2>inline ostream&operator<<(ostream& os,const map<T1,T2>& v){string delim="[";for (typename map<T1,T2>::const_iterator ii=v.begin();ii!=v.end();++ii){os<<delim<<*ii;delim=", ";}return os<<"]";}
// CUT end
class Vehicle
{
public:
int n;
Vehicle(int n):n(n){cout<<"Ctor Vehicle "<<n<<endl;}
Vehicle(Vehicle& v):n(v.n){cout<<"Copy Ctor Vehicle "<<n<<endl;}
virtual ~Vehicle(){cout<<"Dtor Vehicle "<<n<<endl;}
virtual ostream& dump(ostream& os){return os<<"Vehicle("<<n<<")";}
string to_str(){stringstream s; dump(s); return s.str();}
virtual Vehicle& operator++(){n++;return *this;}
virtual Vehicle operator++(int x){Vehicle v(*this); operator++(); return v;}
};
class Car: public Vehicle
{
public:
Car(int n): Vehicle(n){cout<<"Ctor Car "<<n<<endl;}
virtual ~Car(){cout<<"Dtor Car "<<n<<endl;}
virtual ostream& dump(ostream& os){return os<<"Car("<<n<<")";}
virtual Car operator++(int x){Car v(*this); operator++(); return v;}
/* data */
};
ostream& operator<<(ostream& os, Vehicle& v)
{
return v.dump(os);
}
int main(int argc, char const *argv[])
{
Vehicle * v = new Car(10);
// cout<<c++<<endl;
// cout<<c<<endl;
return 0;
}
I get the following error with gcc:
使用 gcc 时出现以下错误:
C:\Users\Rajat\Documents\GitHub\interview-preparation\cpp_test.cpp:16:0: warning: "debug" redefined [enabled by default]
C:\Users\Rajat\Documents\GitHub\interview-preparation\cpp_test.cpp:13:0: note: this is the location of the previous definition
C:\Users\Rajat\Documents\GitHub\interview-preparation\cpp_test.cpp:44:14: error: invalid covariant return type for 'virtual Car Car::operator++(int)'
C:\Users\Rajat\Documents\GitHub\interview-preparation\cpp_test.cpp:35:18: error: overriding 'virtual Vehicle Vehicle::operator++(int)'
C:\Users\Rajat\Documents\GitHub\interview-preparation\cpp_test.cpp: In member function 'virtual Car Car::operator++(int)':
C:\Users\Rajat\Documents\GitHub\interview-preparation\cpp_test.cpp:44:57: error: no matching function for call to 'Car::operator++()'
C:\Users\Rajat\Documents\GitHub\interview-preparation\cpp_test.cpp:44:57: note: candidate is:
C:\Users\Rajat\Documents\GitHub\interview-preparation\cpp_test.cpp:44:14: note: virtual Car Car::operator++(int)
C:\Users\Rajat\Documents\GitHub\interview-preparation\cpp_test.cpp:44:14: note: candidate expects 1 argument, 0 provided
How do I get ++
operators for both Car
and Vehicle
with minimum number of virtual overrides?
我如何获得++
操作符Car
和Vehicle
最少数量的虚拟覆盖?
回答by thefourtheye
Change
改变
virtual Car operator++(int x){Car v(*this); operator++(); return v;}
to
到
virtual Vehicle operator++(int x){Car v(*this); Vehicle::operator++(); return v;}
- While overriding operator++, return type should not be changed.
- Explicitly mention that you want to call parent class's operator++
Vehicle::operator++()
- 在覆盖 operator++ 时,不应更改返回类型。
- 明确提到要调用父类的operator++
Vehicle::operator++()
With that change, your program produces this output
有了这个改变,你的程序就会产生这个输出
Ctor Vehicle 10
Ctor Car 10
回答by Manu343726
Another way to do that is through CRTPand operator overloading helpers (Like boost operators header)
另一种方法是通过CRTP和运算符重载助手(如boost operators header)
Suposse you have the following helper:
假设您有以下帮手:
template<typename T>
struct AddHelper
{
T& operator++()
{
T& reference = static_cast<T&>(*this);
reference.add();
return reference;
}
T operator++(int)
{
AddHelper<T> copy( *this );
operator++();
return static_cast<T>(copy);
}
};
The add()implementation is provided by the base class:
在附加()的实现是由基类提供的:
class Vehicle
{
private:
int _n;
public:
void add(int n) { _n += n; }
...
};
Because Vehicle::add()
is public, we can use it in every Vehicle subclasses, thats means you can have specific operator++ for every Vehicle subclassesthanks to AddHelper:
因为Vehicle::add()
是公共的,我们可以在每个 Vehicle 子类中使用它,这意味着你可以为每个 Vehicle 子类使用特定的 operator++多亏了 AddHelper:
class Car : public Vehicle , public AddHelper<Car>
{
Car(int n) : Vehicle(n) {}
...
};
class Motorcicle : public Vehicle , public AddHelper<Motorcicle>
{
Motorcicle(int n) : Vehicle(n) {}
...
};
class Bus : public Vehicle , public AddHelper<Bus>
{
Bus(int n) : Vehicle(n) {}
...
};
... //Ad infinitum
Another advantage of this way is that it doesnt use virtual functions to provide the polymorphism, so its more efficient (Static polymorphism instead of dynamic polymorphism).
这种方式的另一个优点是它不使用虚函数来提供多态,因此效率更高(静态多态而不是动态多态)。