我可以在需要的地方根据数值自动创建一个类实例吗

Can I automatically create a class instance from a numerical value where needed?

本文关键字:创建 一个 实例 方根 我可以      更新时间:2023-10-16

假设我有一个表示特殊数值的结构,比如添加了功能的浮点。这只是一个例子。

struct MyCustomFloat {
    MyCustomFloat(float value);
    MyCustomFloat(double value);
    ...
};

然后我有了使用该结构实例的其他函数。另一个例子。

MyCustomFloat add(MyCustomFloat x, MyCustomFloat y);

有没有可能实现一种方法,我可以给出int/foat/double/等等。作为这些函数的参数,并将它们自动转换为自定义类型?

这样混乱的代码:

MyCustomFloat result = add(MyCustomFloat(1.5), MyCustomFloat(3.14));

可以用清洁剂代替:

MyCustomFloat result = add(1.5, 3.14);

这将使开发人员不必编写多个版本的函数来接受每种类型的有效构造函数输入。

MyCustomFloat add(int x, int y);
MyCustomFloat add(float x, float y);
MyCustomFloat add(double x, double y);
MyCustomFloat add(int x, double y);
...

可替换为:

它可以,而且您已经实现了一半,因为您已经拥有的构造函数将用于隐式转换

#include <iostream>
class A {
public:    
    A(float f) : val_(f) {}
    A(double d) : val_(d) {}
    A& operator+= (const A& r) {
        val_ += r.val_; 
        return *this;
    }
    double val() const  { return val_; }
private:    
    double val_;    
};
A add(const A& l, const A& r) {
    A a = l;
    a += r;
    return a;
}    
int main()
{
     std::cout << add(3.14f, 2.71).val() << std::endl;    
}

住在Coliru's

如果是这样的话,"清洁"是另一个话题;如果这不是我自己的代码,只会看到main(),我会期望"添加"添加一个POD浮点和一个POD双精度,并惊讶于预期结果(POD)显然有一个花哨的val成员函数all-of-a-sudden

您的问题有几种解决方案:

  • 重载函数:为每个合理的类型和类型组合提供en实现。他们应该只转换参数并用MyCustomFloat参数调用方法。在这种情况下,您不需要重载的Constructor。

  • 运算符:实现const MyCustomFloat MyCustomFloat::operator+(const MyCustomFloat &a)。这样,无论a+b是什么类型,都可以始终将其用作表达式。在这种情况下,您可以编写一个以MyCustomFloat为参数的add函数,并且它们是由重载构造函数构造的。这里不需要过载的add函数。

  • templates:对于一般情况,您需要一个模板化函数,期望参数实现+运算符,即数字类型。此外,您还需要MyCustomFloat的模板专业化。请参阅下面的示例。要混合类型,您需要两个模板化类型和三个专业化。

工作示例:

#include <cstdio>
struct MyCustomFloat {
  double m_value;
public:
  MyCustomFloat(double a) : m_value(a){}
  double get() const {return m_value;}
  // uncomment this for use with operator+                                                                                   
  //const MyCustomFloat operator+(const MyCustomFloat &a) const {return m_value+a.get();}                                    
};
// use this whith operator+                                                                                                  
/*                                                                                                                           
MyCustomFloat add (const MyCustomFloat& a, const MyCustomFloat& b) {                                                         
  return MyCustomFloat(a+b);                                                                                                 
}                                                                                                                            
/**/
// uncomment this for use with template                                                                                      
template <typename T>
MyCustomFloat add(const T& a, const T& b) {
  return MyCustomFloat(a+b);
}
template <>
MyCustomFloat add<MyCustomFloat> (const MyCustomFloat& a, const MyCustomFloat& b) {
  return MyCustomFloat(a.get()+b.get());
}
/**/
int main (void){
  printf("%fn",add(1.2,3.4).get());
  printf("%fn",add(MyCustomFloat(1.2),MyCustomFloat(3.4)).get());
  return 0;
}
相关文章: