Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;创建一个通用接口_C++_Interface_Polymorphism - Fatal编程技术网

C++ C++;创建一个通用接口

C++ C++;创建一个通用接口,c++,interface,polymorphism,C++,Interface,Polymorphism,我有一个接口(缺少很多成员,但请注意这个接口是强制性的)。我需要从中继承5个类,它们将具有_value属性。那么,ins\ 除了实现5个类(对于char、short、int、float、double),我还考虑了一个模板类: class my_interface { public: virtual [various_types] getValue() const = 0; }; template<typename T> class my_class : public

我有一个接口(缺少很多成员,但请注意这个接口是强制性的)。我需要从中继承5个类,它们将具有_value属性。那么,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; }
};
class my\u接口
{
公众:
虚拟[各种类型]getValue()常量=0;
};
模板
类my_类:公共my_接口
{
私人:
T_值;
公众:
my_类(T值):_值(值){}//初始化构造上的属性
虚拟T getValue()常量{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();
}
void my_函数()
{
my_inteface*a=新的my_类(42);
my_interace*b=新的my_类(21);
int结果;
结果=a->getValue()+b->getValue();
}

但我不知道我能做什么。看起来你不能在纯虚拟界面上制作模板。对我来说,唯一可行的方法是使getValue()始终返回一个double,因为它是我需要的最大大小的类型。但是,我不喜欢这种解决方案。

记住“virtual…”的意思是“在类中创建一个函数指针,我将使用它调用正确的派生类”。它只是一个指针,所以在调用它之前,必须就返回类型达成一致。C++没有动态的类型和其他语言的反射——它必须知道调用类型之前的返回类型。

如果您的接口上只有一个方法(GETValueAudio),那么您只需要模板类实现。 但是,如果要创建这样的接口:

std::string getValue();
int getValue();
long 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
}
那么您就不走运了,因为您不能仅基于返回类型重载函数名。或者,您可以创建一个包装器类型

编辑

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

std::string getValue();
int getValue();
long 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();
}
您在这里并没有获得太多,因为用户仍然需要调用包装器的正确子成员。 如果需要,也可以将返回值表示为字符串

请注意,使用活接头时,您需要注意以下注意事项:

编辑2: 你可以用模板返回来实现这一点

template<typename = T>
const T& getVal(const T& typeToAllowMethodOverriding) const;
模板
常数T&getVal(常数T&typeToAllowMethodOverriding)常数;

您也可以将类my_接口设置为模板类:

template<typename T>
class my_interface
{
public:
    virtual T getValue() const = 0;
};
模板
类my_接口
{
公众:
虚拟T getValue()常量=0;
};
这将为您使用的每个类型T生成一个接口和一个类。

template
    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; }
    };
类my_接口 { 公众: 虚拟U getValue()常量=0; }; 模板 类my_类:公共my_接口 { 私人: T_值; 公众: my_类(T值):_值(值){}//初始化构造上的属性 T getValue()常量{return_value;} };

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

我认为您最好使用/实现类似的功能


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

可能的重复项您需要对类型进行所有算术运算还是有限?你总是会遇到这样的问题:你不知道子类的实际类型。你的问题是你根本不能将像
[各种类型]
这样的返回类型作为虚拟函数的返回类型,除非您编写了 MyObjultIs//C>模板类,否则这是不可能的,因为C++是静态类型的语言,返回类型不能从动态类型派生。对于类似问题的实现,您可能需要查看Boost.Variant和/或Boost.Any。但是,没有人能说它是否是你所需要的,因为你没有给我们这背后的原始问题:告诉我们你想要实现什么,而不是如何解决它。@MatthiasBonora:对不起,我需要的是一个接口,而不是抽象类,事实上,你明白,我说的是算术运算符重载。所以是的,我需要所有的算术运算。这行吗?my_接口和my_接口将是不同的类型,因此只有当您有多个相同类型的子类时才会消除接口的点Well,但是如果每个类型只有一个子类,那么这不是一个真正可行的解决方案不,我说在该接口中有其他方法。但是你说的包装类型是什么意思?哦,好吧,我明白你在这里做了什么。但正如您所说,获取值和类模板一样困难。。。事实上,我认为最好是返回一个包含值的模板对象。但我也有同样的问题:我的接口不能有一个返回模板类型的方法……是的,您可以返回模板类型,但前提是您在调用它时知道该类型。您仍然需要提供一种机制来正确重写该方法(使用参数)。见编辑2