自定义模板 class 作为成员的 C++ 向量
C++ vector of custom template class as member
我目前正在使用模板用 C++ 编写程序 class:
template<typename TYPE>
class TemplateClass {
private:
TYPE t;
};
我有另一个 class 作为我的 TemplateClass
的管理器,它应该在一个向量中存储这个 class 的多个实例。不同的实例应该有不同的类型,例如int
、std::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::any
或std::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);
}
}
我目前正在使用模板用 C++ 编写程序 class:
template<typename TYPE>
class TemplateClass {
private:
TYPE t;
};
我有另一个 class 作为我的 TemplateClass
的管理器,它应该在一个向量中存储这个 class 的多个实例。不同的实例应该有不同的类型,例如int
、std::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::any
或std::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);
}
}