【问题标题】:How do I create a template object based off of user input?如何根据用户输入创建模板对象?
【发布时间】:2020-03-14 16:07:02
【问题描述】:

我已经使用模板创建了一个基于数组的队列,以便用户可以决定队列中保存的数据类型,但我无法弄清楚如何收集输入然后从中创建该数据类型的队列。

这是我的队列

    #include <memory>
using namespace std;

template<class itemType>

class Queue
{
private:
   unique_ptr<itemType []> queueArray;
   int queueSize;
   int front;
   int rear;
   int numItems;
public:
   Queue(int);
   itemType peekFront();
   void enqueue(itemType item);
   void dequeue();
   bool isEmpty() const;
   bool isFull() const;
   void clear();
};

我已经尝试过这种方法和许多其他方法,但无法弄清楚如何判断用户输入的数据类型,然后使用该类型的数据创建队列。

    int main()
{
    const int MAXSIZE = 5;
    int choice;

    cout << "1. integer queue\n" << "2. string queue\n" << "3. float queue\n";
    choice = menu();

    if(choice == 1)
    {
        Queue<int> newQueue(MAXSIZE);
        int data;
    }
    else if(choice == 2)
    {
        Queue<string> newQueue(MAXSIZE);
        string data;    
    }
    else if(choice == 3)
    {
        Queue<float> newQueue(MAXSIZE);
        float data;     
    }
    else
        cout << "Number needs to be 1-3." << endl;

    cout << "Enter an item to add" << endl;
    cin >> data;

    newQueue->enqueue(data);

感谢大家的帮助!我几乎已经完成了,但是现在我拥有了所有的虚函数,我该如何调用 peekFront()?既然虚函数不能返回 itemType 对吧?

【问题讨论】:

  • 模板在编译时进行评估。用户输入发生在运行时。因此,模板参数中不能考虑用户输入。充其量,可以为用户输入的每个值实例化模板。这是您在暴露的样本中实际尝试过的。问题是不在if/elses 中的部分无法编译。您可以将整个处理移动到为intfloatstring 实例化的模板函数中。这减少了源代码重复,但不会减少“二进制代码重复”。但这是关于模板的普遍事实。
  • 如果你在if块内创建Queue,它会在离开块时被破坏,所以你以后不能从外面访问它。因此,最后询问数据是没有用的,因为此时newQueue 已不存在。为了解决你的问题,多态是要走的路(或者std::variant,如果你可以使用它)。

标签: c++ arrays templates queue


【解决方案1】:

嗯,你快到了。 您只需要不要松开 datanewQueue 变量的范围。

template <typename T>
T input()
{
    T data;
    cout << "Enter an item to add" << endl;
    cin >> data;
    return data;
}
  int main()
{
    const int MAXSIZE = 5;
    int choice;

    cout << "1. integer queue\n" << "2. string queue\n" << "3. float queue\n";
    choice = menu();

    if(choice == 1)
    {
        Queue<int> newQueue(MAXSIZE);
        newQueue->enqueue(input<int>());    
    }
    else if(choice == 2)
    {
        Queue<string> newQueue(MAXSIZE);
        newQueue->enqueue(input<string>());     
    }
    else if(choice == 3)
    {
        Queue<float> newQueue(MAXSIZE);

        newQueue->enqueue(input<float>());    
    }
    else
        cout << "Number needs to be 1-3." << endl;


}

这个架构你还是有一些问题,比如你可能想把你的queues移到这些ifs之外,否则你就不能再使用它们了。 (阅读scope)。

您也可以查看std::variant 来了解这些情况。

【讨论】:

    【解决方案2】:

    你需要运行时多态来解决这个问题。这可以通过基类来实现:

    class IQueue {
    virtual ~IQueue() = default;
    virtual void enqueue(istream&) = 0;
    };
    
    template<class itemType>
    class Queue : public IQueue
    {
    //...
    public:
        void enqueue(istream& is) override {
            itemType item;
            is >> item;
            enqueue(item);
        }
    //...
    };
    

    并用作指针

    int main() {
        //...
        unique_ptr<IQueue> newQueue;
        //...
        if(choice == 1)
        {
            newQueue.reset(new Queue<int>(MAXSIZE));
            int data;
        }
        //...
        newQueue->enqueue(cin);
        //...
    }
    

    或者类似std::variant

    【讨论】:

      猜你喜欢
      • 2021-11-18
      • 2017-09-11
      • 2018-03-12
      • 1970-01-01
      • 1970-01-01
      • 2013-04-11
      • 2022-01-24
      • 2015-10-31
      相关资源
      最近更新 更多