如何创建自定义类型模板类对象C++

如何创建自定义类型模板类对象C++,c++,templates,C++,Templates,我正在努力允许用户选择数据类型模板将创建为。 由于模板类型必须在编译时定义,所以我必须指定数据类型template将使用egstring、int等,但这意味着我不能在后面更改它,即使我的模板支持它,也不能将其从string更改为int,因为template类对象被声明为string。 我的班级声明如下: template <class T> class MyHashTable { public: string deleted="deleted"; unsigned s

我正在努力允许用户选择数据类型模板将创建为。 由于模板类型必须在编译时定义,所以我必须指定数据类型template将使用egstring、int等,但这意味着我不能在后面更改它,即使我的模板支持它,也不能将其从string更改为int,因为template类对象被声明为string。 我的班级声明如下:

template <class T>
class MyHashTable
{
public:
    string deleted="deleted";
    unsigned short tableSize;
    // array of vectors, hash table container
    vector<T>* myTable;
    vector<T>* deletionTable;

    MyHashTable(unsigned short tableSize) : myTable(new vector<T>[tableSize]),  deletionTable(new vector<T>[tableSize])
    {
        this->tableSize=tableSize;
    }
类外的对象声明

    MyHashTable <string>* myChainedTable=NULL ;
    string tableType;
对象初始化

 if (myChainedTable)
{
    delete myChainedTable;
    myChainedTable=NULL;
}
getType();
if (!myChainedTable)
{
    if (tableType=="string")
        myChainedTable= new MyHashTable<string>(length);  
    if (tableType=="char")
        MyHashTable<char> myChainedTable(length);  // no difference with or without using new keyword
    if (tableType=="double")
        MyHashTable<double> myChainedTable(length);
    if (tableType=="float")
        MyHashTable<float> myChainedTable(length);
    if (tableType=="int")
        MyHashTable<int> myChainedTable(length);

    cout<<tableType<<" table of size "<< length<<" created"<<endl;
我尝试将类对象传递给函数,而不是将其作为全局变量,但也无法使其工作

我真正需要的是一个模板对象,它可以有:int、string、char、double、float类型,我有3个函数需要访问模板类对象,每种情况下有5个不同的对象和200行if语句听起来是最糟糕的解决方案。 我被困在这个问题上有一段时间了,只是不知道怎么做,任何帮助都将不胜感激

void getType()
{
    cout<<"Enter table type, types available: int, char, float, double, string.\n";
    tableType=getInput();
    while((tableType != "int")&&(tableType !="float")&&(tableType !="double")&&(tableType!="char")&&(tableType !="string"))
    {
        cout<<"Invalid type, please try again "<<endl;;
        tableType=getInput();
    }
}

模板在编译时解析。您的容器类型将在运行时解析。模板显然不是这里的解决方案。我想到的第一件事是boost::any和std::vector的组合。

你的问题在模板和变体之间

模板是编译时生成的。因此,您必须在编译时为对象选择所需的类型。您的条件方法无法工作请参阅问题的注释

另一方面,您似乎需要在运行时动态选择类型

如果您想继续使用模板方式:根据注释进行编辑

您需要让所有模板从一个多态基类继承,一个带有虚拟函数的公共接口。例如:

class MyHashBase  // common base class for all templates
{
public:
    virtual void addElement(void *ptrelem) = 0;   // adding an element must be implemented by template. With void* since future template type unknown from base class
    virtual void displayAll() = 0; 
};
然后,模板需要实现虚拟功能:

template <class T>
class MyHashTable : public MyHashBase
{
public:
    unsigned short tableSize;
    vector<T>* myTable;        // I leave it as it is, but you could implement these as vector<T> instead of vector<T>* 
    vector<T>* deletionTable;

    MyHashTable(unsigned short tableSize) : myTable(new vector<T>[tableSize]), deletionTable(new vector<T>[tableSize]), tableSize(tableSize)
    { }
    void addElement(void* ptrelem)
    {   myTable->push_back(*reinterpret_cast<T*>(ptrelem));  }   // reinterpret the void* of the common interface as a T* 
    void displayAll()
    { copy(myTable->begin(), myTable->end(), ostream_iterator<T>(cout, "\n")); }
};
然后可以使用公共API,例如,如果tableType为double:

在调用代码中,如果需要的话,您当然会有一些功能,但是您可以通过仔细设计基类将它们减少到最小。例如,您可以添加一个虚拟克隆函数来复制数据,而不需要调用方知道数据的类型

但是,对基类的公共函数使用单个签名是很麻烦的。为了使虚拟化成为可能,您需要通过void*指针传递参数,void*指针不是很好,而且很容易出错

使用变体的替代方法

您还可以使用它来管理具有动态类型定义的对象

在这种情况下,您不需要为自己的数据结构使用模板。您将使用boost::variant类型的元素创建一个MyHashTable

如果您知道myChainedTable中的对象类型,则可以通过使用:boost::get元素或boost::get,…,访问该对象的正确值

如果您不知道元素的类型,可以使用visitor的概念根据类型自动选择要执行的适当函数

编辑:使用联合体的替代方式:


如果不允许使用变体,另一种选择是使用联合。我不知道rassignment的主题,但您可以选择是使用联合来定义元素(如变量),而不使用模板,还是使用模板类型,但将myChainedTable定义为指向不同模板实例化的指针的联合。但是,是的,它需要大量的if…

从哪里获得tableType?这听起来不像是模板的工作。@Jeffrey更新了我的问题,最初将tableType作为返回语句,在做一些更改时更改为全局变量,但没有多大帮助。编码定义注定会失败。每个都是if语句的本地语句,并且在退出if后立即停止!这是一个任务,我不能使用c++14模板变量,也不能使用c++11,我也不会梦想使用boost;/,模板制作本来应该是任务中很容易的一部分,但我现在被困了一天,模板制作完成了,如果我定义单一类型,一切都可以工作,但是用户需要能够更改当前对象上的数据类型,并且只需要存在一个对象。一定有办法,我是不是把事情搞得太复杂了我希望我错过了一些明显的东西,变体听起来不错,但我不能使用boost。Union看起来就像一个奇特的数组,我仍然需要一堆if语句来知道调用哪一个,但总比什么都不调用要好。你能给我举一个指针方法的例子吗?我已经在用指针调用我的类了,因为我的原始声明是指针,但我不知道如何将一个指针转换成5个对象。我用代码进行了编辑,让clera知道这个选项是如何工作的。干杯,我让步了,只创建了5个不同的对象和巨大的if语句填充函数t o处理它们之间的切换,如果我有时间,我将尝试使用您的第一个示例进行更改。
MyHashBase *myChainedTable = nullptr; 
//...
if (tableType == "string")
    myChainedTable = new MyHashTable<string>(length);
else if (tableType == "double")
    myChainedTable = new MyHashTable<double>(length);
//...
double d1 = 3.1415, d2 = 1.4142; 
myChainedTable->addElement(&d1);   // ATTENTION: you must ensure to provide pointer to the correct data type
myChainedTable->addElement(&d2);
myChainedTable->displayAll();