我正在创建一个2D坐标类(名为“Point”)来帮助我学习C ++。我希望能够对Point类对象(例如Point_a + Point_b)执行基本算术运算(+, - ,*,/ ...)。但是,我还希望能够在Points和其他变量类型(int / float / double)之间执行此类操作。
这可以使用运算符/函数重载来完成。从我下面的代码中可以看出(仅限添加),据我所知,我必须为每个附加变量类型包含两个附加函数,一个用于“Point + int / float / double”形式,另一个用于“int / float / double + Point”形式。
#include <iostream>
using namespace std;
class Point
{
private:
double x, y;
public:
Point(double x_in, double y_in){
setX(x_in);
setY(y_in);
}
// Getters and Setters omitted for brevity
// --- Start of Addition Operator Overloads --- (Code Block A)
friend Point operator+(const Point &p1, const Point &p2); //Point + Point
friend Point operator+(const Point &p1, int val); //Point + Int
friend Point operator+(int val, const Point &p1); //Int + Point
friend Point operator+(const Point &p1, float val); //Point + Float
friend Point operator+(float val, const Point &p1); //Float + Point
friend Point operator+(const Point &p1, double val); //Point + Double
friend Point operator+(double val, const Point &p1); //Double + Point
// --- End of Addition Operator Overloads --- (Code Block A)
};
// --- Start of Addition Operator Overload Functions --- (Code Block B)
Point operator+(const Point &p1, const Point &p2){
return Point(p1.x + p2.x, p1.y + p2.y);
}
Point operator+(const Point &p1, int val){
return Point(p1.x + val, p1.y + val);
}
Point operator+(int val, const Point &p1){
return Point(p1.x + val, p1.y + val);
}
Point operator+(const Point &p1, float val){
return Point(p1.x + val, p1.y + val);
}
Point operator+(float val, const Point &p1){
return Point(p1.x + val, p1.y + val);
}
Point operator+(const Point &p1, double val){
return Point(p1.x + val, p1.y + val);
}
Point operator+(double val, const Point &p1){
return Point(p1.x + val, p1.y + val);
}
// --- End of Addition Operator Overload Functions --- (Code Block B)
int main()
{
Point point_a( 2.00, 20.00);
Point point_b( 0.50, 5.00);
Point point_c = point_a + point_b;
cout << "X = " << point_c.getX() << " and Y = " << point_c.getY() << endl;
return 0;
}
似乎有很多重复,特别是在“Point + int / float / double”类型函数之间。我想知道是否有一种方法可以缩短一点。比方说,我可以拥有一个可以处理所有三个版本的版本,而不是整数,浮点数和双精度版本。例如,将代码块“A”和“B”转换为类似的内容:
...
// --- Start of Addition Operator Overloads --- (Code Block A)
friend Point operator+(const Point &p1, const Point &p2); //Point + Point
friend Point operator+(const Point &p1, int||float||double val); //Point + Int/Float/Double
friend Point operator+(int||float||double val, const Point &p1); //Int/Float/Double + Point
// --- End of Addition Operator Overloads --- (Code Block A)
...
...
// --- Start of Addition Operator Overload Functions --- (Code Block B)
Point operator+(const Point &p1, const Point &p2){
return Point(p1.x + p2.x, p1.y + p2.y);
}
Point operator+(const Point &p1, int||float||double val){
return Point(p1.x + val, p1.y + val);
}
Point operator+(int||float||double val, const Point &p1){
return Point(p1.x + val, p1.y + val);
}
// --- End of Addition Operator Overload Functions --- (Code Block B)
...
上面的代码部分旨在表示所需的结果而不是实际的功能(例如int OR float OR double)。
简而言之,有什么办法可以使“friend Point operator+(const Point &p1, int val);
”及其相应的函数(在代码块B中)接受整数,浮点数和双精度值,或者我需要为每个函数设置一个单独的值变量型?
感谢您的时间。
答案 0 :(得分:5)
通过使用模板和专门化特殊情况可以更加通用,而不是为每种匹配类型提供重载版本:
class Point
{
public:
// ...
template<typename T>
friend Point operator+(const Point &p1, T p2);
};
template<typename T>
Point operator+(const Point &p1, T val){
static_assert(std::is_artithmetic<T>::value,"An arithmetic type is required");
return Point(p1.x + val, p1.y + val);
}
// Specialization for Point
template<>
Point operator+(const Point &p1, const Point& val){
return Point(p1.x + val, p1.y + val);
}
答案 1 :(得分:3)
其他答案提到模板,但实际上,所有数字类型都会自动提升为双打。
因此,您只需要根据Point
和double
提供运营商。
#include <iostream>
using namespace std;
class Point
{
private:
double x, y;
public:
Point(double x_in, double y_in){
setX(x_in);
setY(y_in);
}
// Getters and Setters omitted for brevity
double getX() const { return x; }
double getY() const { return y; }
void setX(double v) { x = v; }
void setY(double v) { y = v; }
// unary ops
Point& operator+=(Point const& other)
{
x += other.x;
y += other.y;
return *this;
}
Point& operator+=(double v)
{
x += v;
y += v;
return *this;
}
// --- Start of Addition Operator Overloads --- (Code Block A)
friend Point operator+(Point p1, const Point &p2)
{
p1 += p2;
return p1;
}
friend Point operator+(Point p1, double val)
{
p1 += val;
return p1;
}
friend Point operator+(double val, Point p1)
{
p1 += val;
return p1;
}
// --- End of Addition Operator Overloads --- (Code Block A)
};
// --- End of Addition Operator Overload Functions --- (Code Block B)
int main()
{
Point point_a( 2.00, 20.00);
Point point_b( 0.50, 5.00);
Point point_c = point_a + point_b;
point_c += 10;
Point point_d = point_c + 10;
Point point_e = point_d + 10.1;
cout << "X = " << point_c.getX() << " and Y = " << point_c.getY() << endl;
return 0;
}
答案 2 :(得分:3)
与模板解决方案分开的解决方案是为要支持的类型定义构造函数,并且只有一个运算符+适用于Point类型。
在调用operator +之前,编译器将隐式调用正确的构造函数来转换内置类型。
这会以浪费的临时对象为代价简化实现。
// Example program
#include <iostream>
#include <string>
class Point {
private:
double x, y;
public:
Point(int val) {
this->x = val;
this->y = val;
}
Point(double x, double y) {
this->x = x;
this->y = y;
}
friend Point operator+(const Point &p1, const Point &p2) {
return Point(p1.x + p2.x, p1.y + p2.y);
}
};
int main()
{
Point p(1,2);
Point q = p + 10;
Point v = 10 + p;
}
有一个关于通过构造函数显式白名单支持的类型的样式论证,以及通过static_asserts列入黑名单。
答案 3 :(得分:2)
您绝对可以使用模板执行此操作:
// inside the class
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
friend Point operator+(const Point &p1, T val) {
// function definition
}
// Don't forget to define the function for T on the left hand side
这使用std::enable_if
和std::is_arithmetic
来使这个函数只接受&#34;算术类型&#34;的类型,基本上是整数和浮点数。
答案 4 :(得分:2)
Point的operator+
实现都会在对元素执行+
之前将其非Point参数转换为双精度数。
float
和int
重载几乎毫无意义。只需编写两个double
重载。
来自int
和float
的内置转化将在operator+
来电中进行。
如果你真的需要int / float重载,并且你知道为什么并且已经测试过双重超载不起作用,请考虑修复损坏的模板转换运算符,这是我能看到这种情况的唯一方法。
如果失败,请明确加倍。
失败,也许可以编写一个模板+
,将任意T
个可兑换为double
,然后转换并调用上面的+
double
。然后添加一段文档,说明为什么必须执行这个愚蠢而复杂的操作,而不是仅使用+
重载double
。然后阅读该段落并改变主意,坚持+
重载double
。