如何在自定义类实例上执行cmath函数?
我可以使用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++来说很新。所以,如果能够做到这一点,我希望得到任何信息,以及这种行为是否不明智,如果是这样,为什么?
在此先感谢。
看一看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);
}
您显示的两种方法是有效的方法。没有办法直接在你的Point类上使用std :: abs。
另一种方法是使您的静态abs1函数成为一个*abs函数。如果它的声明在头文件中,它实际上会重载std :: abs函数。为了将它作为一个免费函数来实现,你需要实现成员函数来获得x和y或者让你的免费函数成为你的Point类的一个朋友。
你会这样做。
#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;
}