如何在C++中同时重载整数,浮点数和双数据类型的运算符

Ada*_* NA 4 c++ math class operator-overloading

我正在创建一个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;
}
Run Code Online (Sandbox Code Playgroud)

似乎有很多重复,特别是在"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)

...
Run Code Online (Sandbox Code Playgroud)

上面的代码部分旨在表示所需结果而不是实际功能(例如int OR float OR double).

简而言之,有什么方法可以使" friend Point operator+(const Point &p1, int val);"及其相应的函数(在代码块B中)接受整数,浮点和双精度值,还是我需要为每个变量类型分别设置一个?

感谢您的时间.

use*_*042 5

通过使用模板和专门化特殊情况可以更加通用,而不是为每个匹配类型提供重载版本:

class Point
{
    public:
        // ...        
        template<typename T>
        friend Point operator+(const Point &p1, T p2);             
};
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)


Ric*_*ges 5

其他答案提到了模板,但实际上,所有数字类型都会自动提升为双精度型。

因此,您只需要提供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;
}
Run Code Online (Sandbox Code Playgroud)


Ala*_*lan 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;
}
Run Code Online (Sandbox Code Playgroud)

关于通过构造函数显式将支持的类型列入白名单以及通过 static_asserts 列入黑名单存在风格上的争论。