Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.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++_Templates_Virtual - Fatal编程技术网

C++ C++;虚拟模板法

C++ C++;虚拟模板法,c++,templates,virtual,C++,Templates,Virtual,我有一个抽象类(我知道它不会以这种方式编译,但它是为了理解我想做的事情): 类抽象计算{ 公众: 模板虚拟void setData(std::string id,T data); 模板虚拟getData(std::string id); }; 类计算:公共抽象计算{ 公众: 模板void setData(std::string id,T data); 模板T getData(std::string id,T data); }; 因此,当我调用setData(“foodoull”,data)时,

我有一个抽象类(我知道它不会以这种方式编译,但它是为了理解我想做的事情):

类抽象计算{
公众:
模板虚拟void setData(std::string id,T data);
模板虚拟getData(std::string id);
};
类计算:公共抽象计算{
公众:
模板void setData(std::string id,T data);
模板T getData(std::string id,T data);
};
因此,当我调用
setData(“foodoull”,data)
时,我希望将
foodoull
标识的double(这里主要关注的不是内部机制)设置为double数据

那怎么做呢


我认为可能有一种方法是键入类似于
virtualvoidsetdata(std::stringid,double data)
的内容,但我不知道如何操作。

使用
boost::any
接受数据,然后在实际设置时,从中获取正确的类型。

您可能可以在您的案例中使用

virtual void setData(std::string id, boost::any data);
它是一个可以封装几乎任何东西的包装器


.

首先,您不能使用
虚拟的
模板功能。由于模板是在编译时解析的,
virtual
将不起作用,因为编译器不知道选择哪个模板。有关这方面的更多信息,请参阅。

问题在于,您无法轻松地将静态时间多态性(模板)与运行时多态性混合使用。在您的示例中,该语言不允许特定构造的原因是,可能有无限多个不同的类型可以实例化模板成员函数,这反过来意味着编译器必须生成代码来动态分派这些类型,这是不可行的

这里可以做不同的事情来绕过限制,基本上可以去掉静态多态性或动态多态性。从等式中删除动态多态性可以通过提供一个非派生的类型来完成,以存储
映射,然后提供只在基本级别解析该映射的模板:

class AbstractComputation {
public:
   template <typename T>
   void setData( std::string const & id, T value ) {
      m_store.setData( id, value );
   }
   template <typename T>
   T getData( std::string const & id ) const {
      return m_store.getData<T>( id );
   }
protected:
   ValueStore m_store;
};

类型擦除是如何在后台实现的很有意思,但在本文的范围之外,重要的部分是
boost::any
是一种具体的(非模板化的)类型,可以通过在参数上使用类型擦除在内部存储任何类型,同时允许对数据进行类型安全检索。

如果您事先知道可能的类型列表,预处理器可能会帮助您:

#define MY_CLASSES MYTYPE(int) MYTYPE(float) MYTYPE(double)

class AbstractComputation {
    public:
#     define MYTYPE(T) virtual void setData(std::string id, T data)=0;\
                       virtual void getData(std::string id, T& dst_data)=0;
      MY_CLASSES
#     undef MYTYPE
};

class Computation : public AbstractComputation {
    public:
#     define MYTYPE(T) virtual void setData(std::string id, T data){std::cout<<"writing: "<<data<<std::endl;}\
                       virtual void getData(std::string id, T& dst_data){dst_data=0;/*put your actual implementation here*/}
      MY_CLASSES
#     undef MYTYPE
};
#定义我的类MYTYPE(int)MYTYPE(float)MYTYPE(double)
类抽象计算{
公众:
#定义MYTYPE(T)虚拟void setData(std::string id,T data)=0\
虚拟void getData(std::string id,T&dst_data)=0;
我的课程
#未定义MYTYPE
};
类计算:公共抽象计算{
公众:

#定义MYTYPE(T)虚拟void setData(std::string id,T data){std::cout在某些情况下,将模板从方法级别移动到类级别就足够了,例如:

#include <iostream>

template<typename T>
class AbstractComputation {
public:
    virtual void setData(std::string id, T data)
    {
        std::cout << "base" << std::endl;
    }
};

template<typename T>
class Computation : public AbstractComputation<T> {
public:
    virtual void setData(std::string id, T data)
    {
        std::cout << "derived" << std::endl;
    }
};

int main()
{
    AbstractComputation<int> *x = new Computation<int>();

    x->setData("1", -1);

    delete x;
    return 0;
}
#包括
模板
类抽象计算{
公众:
虚拟void setData(std::string id,T data)
{

std::cout是关于如何为double创建一个特例的问题。或者如何通过使用一个模板函数来通用地设置任何数据类型。如果一个类型有两个名为“set data”和“get data”的方法,那么可能的重复就是“抽象计算”首先,您可以想到何时命名该类型?我喜欢使用
boost::any
的方法,但不喜欢添加对boost的依赖。但令人高兴的是,六年后
c++17
向该语言添加了(和)。我最终使用
std::any
跨任意用户定义的类型创建了一个API。
#define MY_CLASSES MYTYPE(int) MYTYPE(float) MYTYPE(double)

class AbstractComputation {
    public:
#     define MYTYPE(T) virtual void setData(std::string id, T data)=0;\
                       virtual void getData(std::string id, T& dst_data)=0;
      MY_CLASSES
#     undef MYTYPE
};

class Computation : public AbstractComputation {
    public:
#     define MYTYPE(T) virtual void setData(std::string id, T data){std::cout<<"writing: "<<data<<std::endl;}\
                       virtual void getData(std::string id, T& dst_data){dst_data=0;/*put your actual implementation here*/}
      MY_CLASSES
#     undef MYTYPE
};
#include <iostream>

template<typename T>
class AbstractComputation {
public:
    virtual void setData(std::string id, T data)
    {
        std::cout << "base" << std::endl;
    }
};

template<typename T>
class Computation : public AbstractComputation<T> {
public:
    virtual void setData(std::string id, T data)
    {
        std::cout << "derived" << std::endl;
    }
};

int main()
{
    AbstractComputation<int> *x = new Computation<int>();

    x->setData("1", -1);

    delete x;
    return 0;
}