提问人:John Wong 提问时间:7/14/2023 更新时间:7/14/2023 访问量:85
声明一个没有专用化的基类模板来初始化派生类
Declaring a base class template without specialization to initialize derived class
问:
根据某些参数,我需要使用两个派生类之一。我知道我可以声明基类并使用它来初始化派生类之一。当基类是基类模板时,我该怎么做?
下面是一个简化的方案:
template <class T>
class shape
{
}
class rectangleInt : public shape<int>
{
}
class rectangleDouble : public shape<double>
{
}
int main() {
// I want to do the following
shape<T> shape;
if (args == int) {
shape = rectangleInt();
} else {
shape = rectangleDouble();
}
}
我必须在代码中更改哪些内容才能完成我想要的?
答:
1赞
Mestkon
7/14/2023
#1
不幸的是,它们是不同的、独立的类,因此不能自动互换使用它们。shape<int>
shape<double>
因此,您可以为所有模板创建另一个唯一的基类:
class abstract_shape { };
template<class T>
class shape : public abstract_shape { };
通过这种设计,您实际上可以将指针、所有类派生自 any 的变量存储在 类型的变量中。shape<T>
abstract_shape*
abstract_shape* my_shape1 = &my_double_rect;
abstract_shape* my_shape2 = &my_int_rect;
如果这不能解决问题或不适合设计,可以选择基于的解决方案:std::variant
using shape_ptr = std::variant<std::nullptr_t, shape<int>*, shape<double>*>;
shape_ptr my_shape1 = &my_double_rect;
shape_ptr my_shape2 = &my_int_rect;
第三种选择是单独存储派生自 和 的形状,然后模板化使用它们的函数:shape<int>
shape<double>
std::vector<std::unique_ptr<shape<int>>> my_int_shapes;
std::vector<std::unique_ptr<shape<double>>> my_double_shapes;
template<class T>
auto do_something_with_shape(shape<T>* obj);
auto do_something_with_all_shapes() {
for (auto& int_shape : my_int_shapes) {
do_something_with_shape(int_shape.get());
}
for (auto& double_shape : my_double_shapes) {
do_something_with_shape(double_shape.get());
}
}
评论
0赞
John Wong
7/15/2023
谢谢。对于我的情况来说,解决方案非常优雅。我曾经遇到过一点问题,因为我没有提供完整的细节。该类有一个称为的结构体和一个函数。我收到了这个错误。对于我代码中的这一行,我很困惑。 是一个指针,但错误说它是非指针类型。std::variant
shape_ptr = std::variant<std::unique_ptr<shape<int>>, std::unique_ptr<shape<double>>>;
shape<T>
Foo
Foo bar()
error: base operand of '->' has non-pointer type 'shape_ptr'
while ((foo = shape_ptr->bar())) {
shape_ptr
0赞
John Wong
7/16/2023
in 是指针的名称。打错了字。shape_ptr
while ((foo = shape_ptr->bar())) {
0赞
John Wong
7/16/2023
我解决了。为了后代,以防将来有人需要它,您可以像这样访问该功能std::get<std::unique_ptr<shape<int>>>(indexlr)->bar()
1赞
Mestkon
7/17/2023
如果您不知道 是否包含 a 或 a,那么您可能需要使用 .shape_ptr
shape<int>
shape<double>
std::visit
std::visit([](auto& ptr) { return ptr->bar(); }, my_shape_ptr);
1赞
Mestkon
7/19/2023
如果所有有效都相同,那么我建议将其与模板分开。例如,在上面声明它为或某物。如果这是不可能的,一种替代方法是强制访问者也返回变体shape<T>::Foo
T
shape
shape<T>
shapeFoo
using shapeFoo = std::variant<shape<int>::Foo, shape<double>::Foo>;
std::visit([](auto& ptr) -> shapeFoo { return ptr->bar(); }, my_shape_ptr);
上一个:处理对象操作
下一个:如何迭代 json 对象
评论
rectangleInt
并且不共享一个公共基类,因为 和 是不同的类。rectangleDouble
shape<int>
shape<double>
shape_itf
std::unique_ptr<shape_itf>
shape