【问题标题】:Choosing the data type for a generalized template class in main()在 main() 中为通用模板类选择数据类型
【发布时间】:2012-12-03 03:14:08
【问题描述】:

所以我被要求编写一个简单的向量模板,我相信我已经正确地编写了这个类,查看了我们教科书 (Savitch) 中的一些广义列表示例。现在我试图通过让用户选择数据类型来调用main() 中的类。在声明标识符list1 后,我遇到了问题。在使用 if 语句切换数据类型后,我希望能够使用相同的标识符。但是,我认为 if 语句正文中的语法不正确,因为 list1 已经声明。在java中,我一直认为在声明一个类之后你可以随时调用它的构造函数,但我不知道如何在C++中做到这一点。

#include <iostream>
using namespace std;

template <class T>
class SimpleVector {
    public:
        SimpleVector();
        SimpleVector(int);
        SimpleVector(const SimpleVector & copy);
        ~SimpleVector();
        int size();
        T getElementAt(int n);
        T & operator[](int index);

    private:
        T * item;
        int length;
};


int main() {


    int dType;
    int dataSize;

    cout << "What type of data do you want to enter?\n(1 for integer, 2 for double and 3 for strings)" << endl;
    cin >> dType;
    cout << "How many data inputs? " << endl;
    cin >> dataSize;

    SimpleVector <int> list1; // if I dont declare then for loop doesn't recognize list as a declared variable.
    if (dType == 0) {
        SimpleVector <int> list1(dataSize);
    }
    else if (dType == 1) {
        SimpleVector <double> list1(dataSize);
    }
    else {
        SimpleVector <string> list1(dataSize);
    }

    cout << "Please enter the data:" << endl;
    for (int i = 0; i < dataSize; i++) {
        cin >> list1[i];
    }



    return 0;
}

template <class T> SimpleVector<T>::SimpleVector() {
    item = NULL;
    length = 0;
}
template <class T> SimpleVector<T>::SimpleVector(int s) {
    length = s;
    item = new T[length];

}

template <class T> SimpleVector<T>::SimpleVector(const SimpleVector & copy) {
    int newSize = copy - > size();
    item = new T[newSize];

    for (int i = 0; i < newSize; i++)
    item[i] = copy.item[i];
}

template <class T> SimpleVector<T>::~SimpleVector() {
    delete[] item;
}

template <class T> int SimpleVector<T>::size() {
    return length;
}

template <class T> T SimpleVector<T>::getElementAt(int n) {
    return *(item + n);
}

template <class T> T & SimpleVector<T>::operator[](int index) {
    return this->item[index];
}

【问题讨论】:

    标签: c++ arrays templates generics dynamic


    【解决方案1】:

    您不能切换数据类型。一旦声明为特定类型的变量不能更改为其他类型。

    变量有作用域。

    {
        int a;
        .....stuff.....
    }
    // a cannot be accessed here.
    

    a 现在只能在打开的{ 和关闭的} 之间使用。

    {
        int a; // First a
        .....stuff..... // a refers to the first a here
            {
                int a;
                .....stuff..... // a refers to the second a here
            }
        .....stuff..... // a refers to the first a here
    }
    

    第二个a 是与第一个不同的变量。它只能在它的范围内访问 - 即在离它最近的左大括号和右大括号之间。

    如果你真的想要动态类型,试试Boost.variantBoost.Any

    【讨论】:

    • 谢谢大家,我已经开始拆分我的 if 语句,根据选择的数据类型对列表进行操作。 (我敢肯定,概括读取的数据是最好的方法,但无论是什么重复的代码都不会伤害到我的观点)
    【解决方案2】:

    C++ 和 Java 一样,是一种静态类型和静态范围的语言。这意味着在编译时必须知道变量的类型和生命周期。

    在java中,我一直认为在声明一个类之后你可以随时调用它的构造函数,但我不知道如何在C++中做到这一点。

    这与 Java 没有什么不同。在 Java 中,您正在尝试的操作等同于执行以下操作:

    MyClass c;
    if (cond) {
       MyClass c = new MyClass(1);
    } else  {
       MyClass c = new MyClass(2);
    }
    

    这与调用构造函数无关。这与您在嵌套作用域中声明新变量这一事实有关,并且它们完全独立于外部作用域中的同名变量。

    如果您需要运行时多态,那么(根据定义),您实际上需要使用多态。也就是说,你需要创建一个带有虚函数的通用基类:

    class SimpleVectorBase
    {
    public:
        SimpleVectorBase() { }
        virtual ~SimpleVectorBase() { }
    
        virtual int size() const { return length; }
    
        // ... etc. ...
    
    private:
        int length;
    }
    
    template <class T>
    class SimpleVector : public SimpleVectorBase {
        // ...
    }
    
    int main() {
        // ...
    
        SimpleVectorBase* list1;
        if (dType == 0) {
            list1 = new SimpleVector<int>(dataSize);
        } else if (dType == 1) {
            list1 = new SimpleVector<double>(dataSize);
        } else {
            list1 = new SimpleVector<string>(dataSize);
        }
    
        // ...
    }
    

    但是,这样做并不能真正帮助您处理for 循环。在您的特定情况下,您最好将整个事情模板化:

    template<typename T>
    void doWork(int dataSize)
    {
        SimpleVector<T> list1(dataSize);
        std::cout << "Please enter the data:" << std::endl;
        for (int i = 0; i < dataSize; i++) {
            std::cin >> list1[i];
        }
        // ... Do other stuff with list1 ...
    }
    

    然后你的main() 函数就可以了:

    if (dType == 0) {
        doWork<int>(dataSize);
    } else if (dType == 1) {
        doWork<double>(dataSize);
    } else {
        doWork<string>(dataSize);
    }
    

    【讨论】:

    • 我还有一个关于我的第三个构造函数的问题。它应该实现向量参数的“深拷贝”。我试图简单地创建一个具有输入参数数组大小的新数组。然而这一行: template SimpleVector::SimpleVector(const SimpleVector & copy) { int newSize = copy - > size();//这条线似乎不能正常工作
    • 谢谢大家,我已经开始拆分我的 if 语句,根据选择的数据类型对列表进行操作。 (我敢肯定,概括读取的数据是最好的方法,但无论是什么重复的代码都不会伤害到我的观点)
    • @user1871426:引用不是指针。您需要使用copy.size(),而不是copy-&gt;size()。 (另外,请考虑将 initialization lists 用于构造函数,“copy”是用词不当,因为该参数是被复制的内容,而不是本身的副本。)
    • 将其更改为点运算符时出现以下错误:'->' 的基本操作数具有非指针类型'const SimpleVector<:basic_string> >'
    • 抱歉,错误出现延迟。它实际上说“无效的参数'候选人是:int size()'”
    猜你喜欢
    • 2016-05-31
    • 2022-11-10
    • 2017-09-11
    • 2016-01-07
    • 1970-01-01
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    • 2011-08-01
    相关资源
    最近更新 更多