【问题标题】:How do I allow the user to determine template type?如何允许用户确定模板类型?
【发布时间】:2019-04-15 22:18:53
【问题描述】:

我编写了一个有效的链接队列,它以其数据类型为模板,但是用户可能正在输入几种不同类型之一的数据。如何选择在运行时使用的数据类型?

如果我单独使用每种类型,效果很好;我只需要涵盖所有可能性,而无需更改代码或为每种数据类型重写重载函数。

下面我提供了我的代码的相关部分。正如我所说,我的类成员函数没有问题。

我已经尝试过创建 x 类型版本的队列的 switch 语句,但这不能作为开关中的后续可能性与其他队列数据类型“矛盾”。我目前正在尝试 if/else if 语句,除了当我尝试使用 x 类型的输入时没有错误,它说它是未定义的。

// From Source.cpp

#include <iostream>
#include <string>
using namespace std;
#include "LQueue.h"
int mainMenu();
int main()
{
    int value;
    bool stop = false;
    Queue<int> *theQueue;
    int choice = mainMenu();

    if (choice == 1) {
        Queue<int> theQueue;
        int dataType;
    }
    else if (choice == 2) {
        Queue<double> theQueue;
        double dataType;
    }
    else if (choice == 3) {
        Queue<string> theQueue;
        string dataType;
    }
    else if (choice == 4) {
        Queue<char> theQueue;
        char dataType;
    }

    cout << "\n\nHow many items would you like to initially"
        << " populate the queue with? ";
    int howMany;
    cin >> howMany;

    for (int i = 0; i < howMany; i++)
    {
        cin >> dataType;
        theQueue.enqueue(dataType)
    }

    theQueue.display(cout);

    theQueue.dequeue();

    theQueue.display(cout);

    return 0;
}
int mainMenu()
{
    int choice;
    cout << "What type of data will you be storing in the queue?\n"
        << "1. integers\n2. decimal numbers\n3. words\n4. chars\n\n";

    cin >> choice;
    if (choice > 0 && choice < 5)
        return choice;

    cout << "\n\nInvalid choice\n\n";
    mainMenu();
}
// Guess I'll include shown functions from the Queue class file below

//--- Definition of enqueue()
template <typename QueueElement> 
void Queue<QueueElement>::enqueue(const QueueElement & value)
{
    if (empty())
    {
        myFront = myBack = new Node(value);
    }
    else
    {
        myBack->next = new Node(value);
        myBack = myBack->next;
    }
}

//--- Definition of dequeue()
template <typename QueueElement> 
void Queue<QueueElement>::dequeue()
{
    if (empty() == false)
    {
        Queue::NodePointer oldFront = myFront;
        myFront = myFront->next;
        delete oldFront;
    }
}

//--- Definition of display()
template <typename QueueElement> 
void Queue<QueueElement>::display(ostream & out) const
{
    Queue::NodePointer ptr;
    for (ptr = myFront; ptr != 0; ptr = ptr->next)
        out << ptr->data << "  ";
    out << endl;

}

//--- Definition of front()
template <typename QueueElement> 
QueueElement Queue<QueueElement>::front() const
{
    if (!empty())
        return (myFront->data);
    else
    {
        cerr << "*** Queue is empty "
            " -- returning garbage ***\n";
        QueueElement * temp = new(QueueElement);
        QueueElement garbage = *temp;     // "Garbage" value
        delete temp;
        return garbage;
    }
}

Compiler (visual studio 2017) is showing identifier "dataType" is undefined within the following loop:
```c++

    for (int i = 0; i < howMany; i++)
        {
            cin >> dataType;
            theQueue.enqueue(dataType);
        }

2 错误:“cin >> dataType;”上的 E0020 和 C2065线,还有另一个 下一行 C2065

也许总体上有更有效的方法来做到这一点?我愿意接受任何和所有建议,谢谢!

【问题讨论】:

  • 更新:我在 main 函数的开头添加了一个 typedef.. 并将 if 中的变量声明也更改为 typedefs... 现在可以使用,但是在第一次显示后我丢失了数据();可能是因为我的赋值运算符没有多个定义。对于整数变量,工作得很好......已经感谢那些看过lol xD的人

标签: c++ templates if-statement linked-list switch-statement


【解决方案1】:

问题(一个问题)是当你写的时候

    if (choice == 1) {
        Queue<int> theQueue;
        int dataType;
    }
    else if (choice == 2) {
        Queue<double> theQueue;
        double dataType;
    }
    else if (choice == 3) {
        Queue<string> theQueue;
        string dataType;
    }
    else if (choice == 4) {
        Queue<char> theQueue;
        char dataType;
    }

您定义了四个不同的theQueue 和四个不同的dataType 变量,每一个变量仅在对应的if 的对应主体内有效。

所以,当你写的时候

    for (int i = 0; i < howMany; i++)
    {
        cin >> dataType;
        theQueue.enqueue(dataType)
    }

    theQueue.display(cout);

    theQueue.dequeue();

    theQueue.display(cout);

没有更多的dataTypetheQueue 可用(它们都超出了范围)。

我建议如下

    if (choice == 1) {
        foo<int>();
    }
    else if (choice == 2) {
        foo<double>();
    }
    else if (choice == 3) {
        foo<std::string>();
    }
    else if (choice == 4) {
        foo<char>();
    }

foo() 是一个类似这样的模板函数(注意:代码未经测试)

template <typename T>
void foo ()
 {
   Queue<T> theQueue;
   T        dataType;

   std::cout << "\n\nHow many items would you like to initially"
        << " populate the queue with? ";
   int howMany;
   std::cin >> howMany;

   for (int i = 0; i < howMany; i++)
    {
      std::cin >> dataType;
      theQueue.enqueue(dataType)
    }

   theQueue.display(cout);

   theQueue.dequeue();

   theQueue.display(cout);
 }

【讨论】:

  • 既然 foo() 是模板函数,那么是否应该在头文件中定义它?
  • @K.Rile - 也许吧。或者在调用的同一个 cpp 文件中,如果它在该 cpp 文件中被调用。
  • 太棒了!你的建议非常有效!非常感谢! 10/10 会再问一次大声笑
  • 我提供了一种通过索引查找函数的替代方法
【解决方案2】:

编写一个模板化的成员函数来做你想做的事:

template<class DataType>
void processInput(int howMany) {
    DataType value;

    for (int i = 0; i < howMany; i++)
    {
        cin >> value;
        theQueue.enqueue(value);
    }

    theQueue.display(cout);

    theQueue.dequeue();

    theQueue.display(cout);
}

方法一——switch语句

然后我们可以在main中使用switch语句在它们之间进行选择:

int main()
{
    int choice = mainMenu();

    cout << "\n\nHow many items would you like to initially "
            "populate the queue with? ";
    int howMany;
    cin >> howMany;

    switch(choice) {
      case 1:
        processInput<int>(howMany);
        break;
      case 2:
        processInput<double>(howMany);
        break;
      case 3:
        processInput<string>(howMany);
        break;
      case 4:
        processInput<char>(howMany);
        break;
    }
}

方法 2 - 方法数组

我们可以使用数组来进行查找!

using func_t = void(*)(int);

int main() {

    std::vector<func_t> options = {
        processInput<int>, 
        processInput<double>, 
        processInput<string>, 
        processInput<char>
    };

    int choice = mainMenu();

    func_t selectedOption = options[choice - 1]; 

    cout << "\n\nHow many items would you like to initially "
            "populate the queue with? ";
    int howMany;
    cin >> howMany;

    selectedOption(howMany); 
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 1970-01-01
    • 2021-12-11
    相关资源
    最近更新 更多