如何创建用户定义的类型模板类对象C ++

时间:2014-10-25 12:28:13

标签: c++ templates

我正在努力让用户选择数据类型模板将被创建为。 由于模板类型必须在编译时定义,我必须指定数据类型模板将使用例如(字符串,整数等),但这意味着我不能在后面更改它,即使我的模板支持它,即使字符串为int,因为模板类对象被声明为字符串。 我的课程声明如下:

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();
    }
}

2 个答案:

答案 0 :(得分:2)

您的问题是模板和变体之间的边界。

模板是编译时间。因此,您必须在编译时选择对象所需的类型。您的条件方法不起作用(请参阅提问题)。

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

如果您想继续使用模板方式:(根据评论进行修改)

您需要从单个多态基类继承所有模板(一个具有虚函数的通用接口)。示例:

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")); }
};

然后,您可以让myChainedTable成为指向公共基类型的指针,并以对字符串大小写(即使用new)的方式初始化此指针。

MyHashBase *myChainedTable = nullptr; 
//...
if (tableType == "string")
    myChainedTable = new MyHashTable<string>(length);
else if (tableType == "double")
    myChainedTable = new MyHashTable<double>(length);
//...

然后,您可以使用通用API,例如,如果tableType"double"

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

如果在调用代码中需要,你肯定会有一个coupe,但你可以通过仔细设计基类来减少它们(例如,你可以添加一个虚拟克隆函数,复制数据而不需要知道呼叫者的类型)。

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

使用变体的替代方式

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

在这种情况下,您不需要自己的数据结构模板。您可以使用MyHashTable类型的元素创建boost::variant< int, std::string, ... >

如果您知道其类型(如在myChainedTable中),则可以使用:boost::get<int> (element)(或boost::get<string>(),...)来访问对象的正确值。

如果你不知道元素的类型,你可以使用“visitor”的概念自动选择适当的函数来exectue,具体取决于类型。

修改:与工会的替代方式:

如果您不允许使用变体,则另一种替代方法可以使用union。我不知道你的主题,但是你可以选择使用联合来定义元素(比如变体,没有模板)或者像你一样使用模板类型,但定义myChainedTable成为指向不同模板实例的指针的联合。但是,是的,它需要很多if s ...

答案 1 :(得分:0)

模板在编译时解析。您的容器类型在运行时解析。模板显然不是这里的解决方案。我首先想到的是boost::anystd::vector的组合。