由于模板函数而在条件语句之外声明类对象的问题

时间:2011-03-16 07:26:51

标签: c++ templates function conditional declaration

对于我的c ++类,我们的任务是编写一个模板类,用户使用模板定义类对象的类型。

来自main的代码片段:

if (dataType == "1" || dataType == "int") {  
    simpleVector<int> userArray;  
} else if (dataType == "2" || dataType == "double") {  
    simpleVector<double> userArray;  
} else if (dataType == "3" || dataType == "char") {  
    simpleVector<char> userArray;  
} else if {  
    simpleVector<string> userArray;  
}  
userArray.setDefaultArray();

从此我得到错误代码C2065 - 未声明的标识符错误。我知道为什么我收到错误但我不知道如何在知道数据类型之前声明userArray。

源代码:

#include <stdio.h>
#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

template<class T>
class simpleVector {
public:
    void setDefaultArray ();
    void setArraySize (int size);
    void copy (T *arr);
    void desctruct ();
    int getArraySize ();
    T getElementAt (int index);
    void fillArray();
private:
    int arraySize;
    T *myArray;
};

int main () {
    string dataType;
    int arraySize;
    bool loopCondition = false;

    do {
        cout << "Data Type:"; 
        cin >> dataType;
        if (dataType == "1" || dataType == "2" || dataType == "3" || dataType == "4" 
        || dataType == "int" || dataType == "double" || dataType == "char" || dataType == "string") {
            loopCondition = false;
        } else {
            cout << "WARNING: invalid data type entered." << endl;
            cout << "Valid entries are (1.int, 2.double, 3.char, 4.string)" << endl;
            loopCondition = true;
        }
    } while (loopCondition);

    if (true) 
        int num = 9;
    else
        int num = 7;

    int num2 = num;

    //simpleVector userArray; //?? Review

    if (dataType == "1" || dataType == "int") {
        simpleVector<int> userArray;
    } else if (dataType == "2" || dataType == "double") {
        simpleVector<double> userArray;
    } else if (dataType == "3" || dataType == "char") {
        simpleVector<char> userArray;
    } else if (dataType == "4" || dataType == "char") {
        simpleVector<string> userArray;
    }
    userArray.setDefaultArray();
    cout << "Number of Inputs:"; 
    cin >> arraySize;
    userArray.setArraySize(arraySize);
    userArray.fillArray();

    return 0;
}

//Should call desctruct before this if reusing.
template<class T>
void simpleVector<T>::setDefaultArray() {
    arraySize = 0;
    myArray = NULL; //note: NULL is case sensitive (#include <stdio.h>)
}

template<class T>
void simpleVector<T>::setArraySize (int size) {
        myArray = new T[size];
}

template<class T>
void simpleVector<T>::copy (T *arr) {
//ToDo
}

template<class T>
void simpleVector<T>::desctruct () {
//ToDo
}

template<class T>
int simpleVector<T>::getArraySize () {
//ToDo
}

template<class T>
T simpleVector<T>::getElementAt (int index) {
//ToDo
}

template<class T>
void simpleVector<T>::fillArray() {
    cout << "Enter Array Values" << endl;
    for (int i; i < arraySize; i++) {
        cout << "Element " + i + ":";
        cin >> myArray[i];
    }
}

谢谢,

麦克

3 个答案:

答案 0 :(得分:2)

Eugene的答案中的代码看起来很棒,但是对于学习C ++来说可能太复杂了?

一个非常简单的解决方案可能看起来像这样

  • 声明一个类vectorBase,它声明了所有向量中需要的所有方法
  • 让模板化的类继承自vectorBase
  

模板       class simpleVector:public vectorBase {...

  • 然后在
  • 之前声明一个类型为vectorBase的指针
  

if(dataType ==“1”|| dataType ==“int”)...

    if-block中的
  • 将新创建的userArrays分配给基类指针
  • 稍后,通过baseClass指针访问方法,该指针对于所有特定模板类
  • 是相同的

答案 1 :(得分:0)

您无法执行此操作,因为类型确定是编译时进程。如果要在运行时确定类型,请使用继承而不是模板。 我也可以建议你“变种”模式。例如:

#include <memory>
#include <string>

class variant
{
public:

    template <class T>
    variant& operator = (T const& t)
    {
        typedef type<T> assign_type;
        object = std::auto_ptr<assign_type>(new assign_type(t));
        return *this;
    }

    template <class T>
    operator T ()
    {
        typedef type<T> assign_type;
        assign_type& type = dynamic_cast<assign_type&>(*object);
        return type.get();
    }

private:

    class base
    {
    public:

        virtual ~base() {}
    };

    typedef std::auto_ptr<base> base_ptr;

    template <class T>
    class type : public base
    {
    public:

        type(T const& t)
        : object(t)
        {
        }

        T get() const
        {
            return object;
        }

    private:

        T object;
    };

    base_ptr object;
};

struct dummy
{
    int a;
    int b;
    int c;
};

int main()
{
    variant v1, v2, v3, v4;

    v1 = 2;
    v2 = 5.0f;
    v3 = std::string("Pot of gold");
    v4 = dummy();

    int         i = v1;
    float       f = v2;
    std::string s = v3;
    dummy       d = v4;

    return 0;
}

答案 2 :(得分:0)

据我了解,此问题的目的是教导模板使用如何受编译时类型定义的限制。用户的选择将受到开发人员关心明确指定的某些类型列表的限制,这非常简单。现在问题是 - 它如何影响最终的程序?

首先,您应该意识到模板参数的所有可能值的代码路径将在编译时实例化。换句话说,将为setDefaultArray生成setArraySizefillArrayint和您在通用算法中明确或隐式调用的其他成员函数的二进制代码,{{ 1}},doublechar模板参数。您无法从可执行文件中优化它。

但是,您可以做的是决定如何以最有效的方式将对象存储在内存中。显然,对于您的任务,您一次只需要一个std::string个实例。因此,您可能会想到一个足够大的内存块来保留任何simpleVector实例,并指定它们当前包含哪些实例。在C ++中,它听起来像这样:

simpleVector

请注意,您只能使用POD结构(谷歌定义)。 基于继承的方法最终归结为这种布局。

要完成图片,我们只需要将处理逻辑连接到此数据结构:

struct SimpleVectors {
    VectorTypeEnum vte;
    union {
        simpleVector<int> v_int;
        simpleVector<double> v_double;
        simpleVector<char> v_char;
        simpleVector<string> v_string;
    };
};

这种方法相对于基于继承的好处是,您可以使您的类成员函数内联,并且编译器将注意它们的调用将比虚拟成员函数快一个数量级。

最后,template < typename T > inline void handleTask ( simpleVector < T > & v ) { int arraySize; v.setDefaultArray(); cout << "Number of Inputs:"; cin >> arraySize; v.setArraySize(arraySize); v.fillArray(); } 函数的关键部分将如下所示:

main