C++ 基类中编译时派生模板类的大小
我有一个现有的体系结构,它使用多态容器来保存派生模板类的实例。现在我需要重写基类中的一个运算符,并在编译时用派生类的大小声明一个类型。C++ 基类中编译时派生模板类的大小,c++,templates,polymorphism,C++,Templates,Polymorphism,我有一个现有的体系结构,它使用多态容器来保存派生模板类的实例。现在我需要重写基类中的一个运算符,并在编译时用派生类的大小声明一个类型。 该体系结构如下图所示: 我已经在基类头中尝试了模板类的前向声明,但没有成功。我还尝试用基类制作一个模板来获取类类型,但这对多态容器不起作用 提前感谢您的设计存在的问题是,模型类无法知道其派生类的大小,如果它不知道是哪个类派生它。 正如您正确指出的,将模型本身作为类模板将阻止您创建模型的动态容器 为了解决这个问题,您可以添加一层静态多态性(也称为CRTP)来实现
该体系结构如下图所示: 我已经在基类头中尝试了模板类的前向声明,但没有成功。我还尝试用基类制作一个模板来获取类类型,但这对多态容器不起作用
提前感谢您的设计存在的问题是,
模型
类无法知道其派生类的大小,如果它不知道是哪个类派生它。
正如您正确指出的,将模型
本身作为类模板将阻止您创建模型
的动态容器
为了解决这个问题,您可以添加一层静态多态性(也称为CRTP)来实现您想要的
其思想是从模板基类ModelCRTPBase
派生Model
,然后将接口功能委托给实际实现
显然,知道其子级大小的仍然不是Model
类,而是ModelCRTPBase
。但是由于模型
仅用作多态接口类,并且模型的所有常见功能都在ModelCRTPBase
中(它在编译时知道大小),这应该不是问题
#include <iostream>
#include <vector>
#include <memory>
class Model {
public:
virtual ~Model() {}
virtual void print() = 0;
};
template<typename Derived>
class ModelCRTPBase : public Model {
Derived& derived() {
return static_cast<Derived&>(*this);
}
public:
static size_t size() {
return sizeof(Derived);
}
void print() override {
std::cout << "print Base, size = " << size() << '\n';
derived().print_impl();
}
};
template <typename T>
class ModelA : public ModelCRTPBase<ModelA<T>> {
public:
void print_impl() {
std::cout << "ModelA<" << typeid(T{}).name() << ">\n";
}
};
template <typename T>
class ModelB : public ModelCRTPBase<ModelB<T>> {
int payload;
public:
void print_impl() {
std::cout << "ModelB<" << typeid(T{}).name() << ">\n";
}
};
int main() {
std::vector<std::shared_ptr<Model>> vec;
vec.push_back(std::make_shared<ModelA<int>>());
vec.push_back(std::make_shared<ModelB<float>>());
vec[0]->print();
vec[1]->print();
}
#包括
#包括
#包括
类模型{
公众:
虚拟~Model(){}
虚空打印()=0;
};
样板
类ModelCRTPBase:公共模型{
派生&Derived(){
返回静态_cast(*此);
}
公众:
静态大小\u t大小(){
返回sizeof(派生);
}
void print()覆盖{
std::cout似乎您有一个设计问题。您需要模型的所有可能选项
?即使是在这个阶段您不知道的选项?当继承类知道其继承类时,就已经存在设计问题,而模板类的设计问题似乎最糟糕。为什么您需要在编译时而不是在执行时知道大小按时(virtual size\t sizeOf()const=0;
on Model并在ModelA和ModelB上实现)似乎在这背后有一个有趣的问题,但并不清楚。我知道体系结构更糟糕,但它是给定的。我需要在编译时使用它,因为我需要在重写的运算符中使用模板类。
print Base, size = 8
ModelA<i>
print Base, size = 16
ModelB<f>