自定义模板 class 作为成员的 C++ 向量

C++ vector of custom template class as member

我目前正在使用模板用 C++ 编写程序 class:

template<typename TYPE>
class TemplateClass {
private:
    TYPE t;
};

我有另一个 class 作为我的 TemplateClass 的管理器,它应该在一个向量中存储这个 class 的多个实例。不同的实例应该有不同的类型,例如intstd::string 等。以 Java 的方式来说,解决方案是只使用下面示例中的内容,但似乎这在 C++ 中是不可能的。

class ManagerClass {
private:
    // Here seems to be the problem. 
    std::vector<TemplateClass<?>> templates;
}

是否可以这样做?

谢谢大家的回答

这是通过运行时 多态 实现的一种方法,这是通过函数覆盖实现的。 函数覆盖发生在派生class具有基class的成员函数之一的定义时。该基函数据说被覆盖

#include <iostream>
#include <vector>

using namespace std;

// Base class declaration
class Base {
public:
    virtual void print()
    {
        cout << "Base" << endl;
    }
    virtual ~Base(){}
};

// Derived Class 1 
class Derived1 : public Base {
public:
    void print()
    {
        cout << "Derived1" << endl;
    }
};

// Derived class 2 
class Derived2 : public Base {
public:
    void print()
    {
        cout << "Derived2" << endl;
    }
};


int main()
{
    Base* d1 = new Derived1();
    Base* d2 = new Derived2();

    vector<Base*> myVec;
    myVec.push_back(d1);
    myVec.push_back(d2);

    for (auto i : myVec) {
        i->print();
    }

    delete d1;
    delete d2;

    return 0;
}

如果你会用C++17,你可以用std::anystd::variant

class ManagerClass {
private:
    using variant_type = std::variant<
          TemplateClass<std::string>,
          TemplateClass<int>,
          TemplateClass<double> >;
    std::vector<variant_type> templates;
};

如果您知道编译时将存储在 std::vector 中的所有类型,我会在这种情况下使用 std::variant

// This is used for the visitor pattern.
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
// The below line not needed in C++20...
template<class... Ts> overload(Ts...) -> overload<Ts...>; 

template<typename T>
struct MyClass { T value; };

using types = std::variant<
    MyClass<std::string>, 
    MyClass<int>, 
    MyClass<double>>;

int main() 
{
    std::vector<types> stuff{};
    stuff.push_back(MyClass<std::string>{});
    stuff.push_back(MyClass<int>{});
    stuff.push_back(MyClass<double>{});

    for(const auto& v : stuff) 
    {
        if (std::holds_alternative<MyClass<std::string>>(v)) 
        {
            std::cout << "Im a string\n";
        }
        else if (auto* p{std::get_if<MyClass<int>>(&v)})
        {
            std::cout << "Im an int\n";
        }
        else 
        {
            auto t = std::get<MyClass<double>>(v);
            std::cout << "Im a double\n";
        }

        // Or you can use the visitor pattern.
        std::visit(overload{
            [](const MyClass<std::string>& ) { std::cout << "I'm a string\n"; },
            [](const MyClass<int>& ) { std::cout << "I'm a int\n"; },
            [](const MyClass<double>& ) { std::cout << "I'm a double\n"; },
        }, v);
    }
}