我可以根据需要从数值中自动创建类实例吗?

时间:2015-11-19 06:31:01

标签: c++

假设我有一个表示特殊数值的结构,就像具有附加功能的浮点数一样。这只是一个例子。

struct MyCustomFloat {

    MyCustomFloat(float value);
    MyCustomFloat(double value);

    ...
};

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

MyCustomFloat add(MyCustomFloat x, MyCustomFloat y);

是否可以实现一种方法,我可以给出一个int / float / double / etc。作为我这些函数的参数,让它们自动转换为自定义类型?

这样凌乱的代码:

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);
...

2 个答案:

答案 0 :(得分:3)

  

可以替换为:

它可以,并且您已经半途实施了它,因为您已经拥有的构造函数将用于implicit conversion

#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;    
}

live在Coliru的

如果那是“更干净”是一个不同的主题;如果这不是我自己的代码并且只看到main(),我会期望“添加”添加POD浮点数和POD双倍,并且惊讶于预期结果(POD)显然具有花哨的val成员函数突然之间。

答案 1 :(得分:0)

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

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

  • 运营商:实施const MyCustomFloat MyCustomFloat::operator+(const MyCustomFloat &a)。这样,您可以始终使用a+b作为表达式,无论它们是什么类型。在这种情况下,您可以编写一个add函数,将MyCustomFloat作为参数,它们是从重载的构造函数构造的。这里不需要重载add功能。

  • 模板:对于一般情况,您需要一个模板化函数,期望参数实现+运算符,即数值类型。此外,您需要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("%f\n",add(1.2,3.4).get());
  printf("%f\n",add(MyCustomFloat(1.2),MyCustomFloat(3.4)).get());
  return 0;
}