2017-10-12 99 views
1

我可以使用C++中的任何方法,例如重载或模板,这将允许我将类实例作为参数传递给cmath函数吗?例如,如果我有一个名为“点”(如下所示)的类,有什么方法可以执行操作std::abs(Point(-4, -9))并使其返回Point(4, 9)如何在自定义类实例上执行cmath函数?

#include <iostream> 
#include <cmath> 

class Point{ 
    private: 
     double x, y; 

    public: 
     Point(double x, double y) { 
      this->x = x; 
      this->y = y; 
     } 

     // Approach 1 that I would like to avoid 
     static Point abs1(const Point &p1) { 
      return Point(std::abs(p1.x), std::abs(p1.y)); 
     } 

     // Approach 2 that I would like to avoid 
     Point abs2(void) { 
      return Point(std::abs(x), std::abs(y)); 
     } 
}; 

int main() 
{ 
    Point pt1(-4.0, -9.0), pt2; 

    pt2 = std::abs(pt1) // <-- What I would like to be able to do 

    pt2 = Point::abs1(point_d); // <-- Function call 1 that I would like to avoid 
    pt2 = point_d.abs2(); // <-- Function call 2 that I would like to avoid 

    return 0; 
} 

还是我仅限于使用需要我类为基础的方法调用Point::abs(Point(-4, -9))Point(-4, -9).abs()?总而言之,我可以扩充cmath函数来接受一个类实例吗?

我看了一下,我找不到关于这个主题的任何信息,但是我对C++来说很新。所以,如果能够做到这一点,我希望得到任何信息,以及这种行为是否不明智,如果是这样,为什么?

在此先感谢。

回答

2

看一看this参考页:

为了计算绝对值,在CMATH你只是有一堆重载,关于原始类型的操作:

int abs(int j); 
    long int abs(long int j); 
    long long int abs(long long int j); 
    float abs(float j); 
    double abs(double j); 
    long double abs(long double j); 

由于这些功能不是模板化的,你无法将Point类传递给它们,并返回Point的另一个实例。他们只能接收一个原始类型,并返回相同的类型。

只有当您的Point类可以转换为其中一种基本类型时,才会发生类似的情况(类似于语法)。例如。在下面的代码片段中,我定义了可隐式转换为int的类A,因此当我使用A的实例调用abs时,它会自动转换为int,并传递给的相应超载,最后得到的结果是转换回A.

#include <cmath> 
#include <iostream> 


class A 
{ 
public: 
    A(int x_) // implicit conversion from int 
    : x(x_) 
    {} 

    operator int() 
    { 
     return x; // implicit conversion to int 
    } 
private: 

    int x; 
}; 


int Foo(int x) 
{ 
    return x * 2; 
} 

int main() 
{ 
    A a1(-2); 
    A a2 = Foo(a1); 
    A a3 = std::abs(a1); 

    std::cout << "a2: " << a2 << "\n"; 
    std::cout << "a3: " << a3 << "\n"; 

    getchar(); 
} 

但是,这是非常多的你可以去这个伎俩,我认为不包括你想要的。我相信在你的情况下最好的办法是创建一些实用功能,这就是你想要的。我宁愿去一个免费的功能,而不是一个静态的成员,不要用不必要的实用方法给班级乱扔垃圾,即像这样的东西

namespace PointUtils 
{ 
    Point abs(const Point& p); 
} 
1

您显示的两种方法是有效的方法。没有办法直接在你的Point类上使用std :: abs。

另一种方法是使您的静态abs1函数成为一个自由abs函数。如果它的声明在头文件中,它实际上会重载std :: abs函数。为了将它作为一个免费函数来实现,你需要实现成员函数来获得x和y或者让你的免费函数成为你的Point类的一个朋友。

1

你会这样做。

#include <iostream> 
#include <cmath> 

class Point{ 
     double x, y; 

    public: 
     Point(double x, double y) 
     : x(x), y(y) 
     { 
     } 

    friend Point abs(const Point &p1) { 
     return Point(std::abs(p1.x), std::abs(p1.y)); 
    } 
}; 


int main() 
{ 
    using std::abs; 

    Point pt1(-4.0, -9.0); 
    double x = 5.5; 

    // this will work even if Point is in its own namespace 
    // because of ADL 
    Point pt2 = abs(pt1);  

    // this works because for this function, we have pulled 
    // std::abs into the global namespace 
    double y = abs(x); 

    return 0; 
} 
相关问题