使用自定义类型定义多个具有相同名称的函数

Defining multiple functions with the same name using custom types

我一直在研究 C++,但我注意到一些我不太理解的东西:

typedef float degrees;
typedef float radians;

void my_func(degrees n);
void my_func(radians m);

像这样声明一个函数,我收到一条警告,该函数被重新声明,就好像它们是相同的一样。这是否意味着,在查看函数定义时,编译器只看到内置类型而不关心自定义类型,并且由于它们是 bot float,它只是将它们视为相同的函数?...

如果是这种情况,我该如何解决这个问题?我只需要做一个不同的功能吗?

您可以定义类来处理这些问题。看这个例子:

class Degree{
public:
  double angle;
  Degree(){}
  void my_func(){
    // do some job
  }
};

class Radian{
public:
  double angle;
  Radian(){}
  void my_func(){
    // do some job
  }
};

int main(){
  Degree deg;
  Radian rad;

  deg.my_func();
  rad.my_func();
}

现在他们在各自的职能中执行不同的任务。

或者如果你不想创建对象,你可以在这些 类.

中创建一个静态函数
class Radian{
public:

  static void my_func(float radian){
    // do some job
  }
};

typedef float degrees;
typedef float radians;

int main(){
  radians rad;

  Radian::my_func(rad)
}

typedef 仅为现有类型创建一个新名称,因此在您的示例中,编译器将度数、弧度和浮点数关联为相同的数据类型。他们不是说自定义类型,而只是 pre-existing 类型的新名称。

问题是您没有使用 2 种不同的类型,而是对同一类型使用了 2 个不同的别名,因此对于编译器来说,它是相同的函数。

现在有多种解决方法:

第一个可以声明 2 个不同的 类,只有一个 float 类型的属性,如果你想隐式转换为 double 的 float,请按这种方式重新实现转换:

class Radian{
public:
  float angle;
  Radian(){};
  operator float() { return angle; }
};

另一个解决方案可以声明 2 个不同的函数名称,例如:

void my_func_deg(degrees n);
void my_func_rad(radians m);

或使用内部函数创建 2 个不同的 类:

 class Radian{
public:
  double angle;
  Radian(){};
  void my_func();
};

另一种可能性是定义 RadianDegree classes 以从 floats 进行显式转换并隐式转换它们。

class Radian{
    float m_value;
public:
    explicit Radian(float t_value) : m_value(t_value) { }
    operator float() const { return m_value; }
};

class Degree{
    float m_value;
public:
    explicit Degree(float t_value) : m_value(t_value) { }
    operator float() const { return m_value; }
};

void my_func(Radian r);
void my_func(Degree d);

my_func(Radian(10)); // calls the Radian overload
my_func(Degree(10)); // calls the Degree overload
my_func(10); // Doesn't call either because both ctors are explicit


float 的隐式转换意味着您可以将 RadianDegree 类型的变量传递给需要 float 的函数,它就会正常工作。


这个版本确实意味着,与 typedefs 不同,您将无法编写

Degree alpha = 30;
Degree beta = 60;
Degree gamma = alpha + beta; // 90 degrees

但是,如果需要,您也可以为每个 class 定义算术运算符,例如 operator+operator* 等。例如,您可能希望始终以 360 为模执行度数算术,以便 180 + 180 = 0.