C ++创建一个通用接口

时间:2014-02-21 10:45:14

标签: c++ interface polymorphism

我有一个接口(缺少很多成员,但请注意这个接口是必需的)。我需要继承5个类,它们将具有_ 属性。所以,ins \ 实现了5个类(用于char,short,int,float,double),我想到了一个模板类:

class my_interface
{
public:
    virtual [various_types]    getValue() const = 0;
};

template<typename T>
class my_class : public my_interface
{
private:
    T    _value;
public:
    my_class(T value) : _value(value) {} // initialize the attribute on construct
    virtual T        getValue() const { return _value; }
};

...这样的东西可以起作用:

void                my_function()
{
    my_inteface*    a = new my_class<char>(42);
    my_interace*    b = new my_class<short>(21);
    int             result;

    result = a->getValue() + b->getValue();
}

但我不明白我该怎么做。看来你无法在界面纯虚拟上制作模板。对我来说,唯一可行的方法是让 getValue()始终返回一个double,因为它是我需要的最大尺寸类型。但是,我不喜欢这个解决方案。

5 个答案:

答案 0 :(得分:1)

如果您的接口只有一个方法(getValue()),那么您只需要模板类实现。

但是如果你想要这样的界面:

std::string getValue();
int getValue();
long getValue();

然后你运气不好,因为你不能只根据返回类型重载函数名。或者,您可以创建包装类型。

修改

通过包装器类型我的意思是,如果需要getValue来返回多个类型,您可以使用封装类以多种方式执行此操作,该封装类封装了您所需的功能,而不是将其添加到顶级接口。它可能看起来像这样:

enum ValType{
  INT, CHAR, STR, DEQUE
};

class Wrapper{
private:
  union S{
    int intVal;
    char charVal;
    std::string stringVal;
    std::deque dequeVal;
    ~S() {}
  } theVal;

  ValType heldType;
public:
  void setVal(int value){ heldType = INT; theVal.intVal = value; }
  void setVal(char value){ heldType = CHAR; theVal.charVal = value; }
  // ... and so on
  int getIntVal() const {
    if(heldType!=INT) 
      throw std::runtime_error("Cop on");
    return theVal.int;
  }
  // and so on
}

然后你的界面是

public class my_interface{
  virtual Wrapper getVal();
}

由于用户仍需要调用Wrapper的正确子成员,因此您在这里并没有获得太多收益。 如果需要,您也可以将返回值表示为字符串。

请注意,使用工会时,您需要注意警告: http://en.cppreference.com/w/cpp/language/union

编辑2: 你可以用模板化的回报来做到这一点

template<typename = T>
const T& getVal(const T& typeToAllowMethodOverriding) const;

答案 1 :(得分:0)

请记住,'virtual ...'表示“在类中创建一个函数指针,用于调用正确的派生类”。它只是 一个指针 - 所以你必须在调用之前就返回类型达成一致。 C ++没有动态类型和其他语言的反映 - 在调用之前必须知道返回类型是什么。

答案 2 :(得分:0)

你也可以让my_interface类成为模板类:

template<typename T>
class my_interface
{
public:
    virtual T getValue() const = 0;
};

这将为您使用的每个类型T生成一个接口和一个类。

答案 3 :(得分:0)

    template<typename U>
class my_interface
    {
    public:

        virtual  U  getValue() const = 0;
    };

    template<typename T>
    class my_class : public my_interface<T>
    {
    private:
        T    _value;
    public:
        my_class(T value) : _value(value) {} // initialize the attribute on construct

           T getValue() const { return  _value; }
    };

它适用于所有类型,但对于字符串类型,您必须对模板进行专门化

答案 4 :(得分:0)

我认为你最好的方法是使用/实现像boost::variant这样的东西。

typedef boost::variant<char, short, int, float, double> Value;

class my_interface
{
public:
    virtual Value getValue() const = 0;
};

template<typename T>
class my_class : public my_interface
{
private:
    T    _value;
public:
    my_class(T value) : _value(value) {} // initialize the attribute on construct
    virtual Value getValue() const { return _value; }
};

然后你可以实现算术运算符:

Value operator+(const Value &lhs, const Value &rhs) {
    //Check the internal types of lhs and rhs and perform the operation
}

您还可以将boost::variant打包到另一个类中,以便为基本类型提供转换运算符。