通用对象向量/数组,其中每个存储的对象都有不同的类
Posted
技术标签:
【中文标题】通用对象向量/数组,其中每个存储的对象都有不同的类【英文标题】:Generic object vector/array, where each stored object has a different class 【发布时间】:2017-10-27 13:54:53 【问题描述】:有什么方法可以制作通用对象向量或数组,让我可以将不同类的对象保存在单个向量或数组中。
我基本上想知道我是否可以切换出调用了哪个版本的类。
即类 square 被类 circle 替换,但两者都有一个名为 findArea 的函数,因此在调用该对象向量/数组时主函数不会中断。
【问题讨论】:
如果您只想使用通用功能,哪些不能存储指向基类的指针 (std::unique_ptr
)?
定义“不同的类”。完全不相关,还是只是共同基础的不同子类?看,由于含糊不清,您已经引出了两个完全不同的答案,其中大概只有一个实际上适用于您。如果是后者,那就简单研究基础多态性;我们不需要解释虚函数。
如果是前者,那么:How can I store objects of differing types in a C++ container?的可能重复
【参考方案1】:
您将需要某种间接方式。
std::vector<std::unique_ptr<Shape>> array_of_shapes;
所有形状都是 Shape 派生的类。
如果 Shape 有一个virtual findArea()
,那么您可以随时调用array_of_shapes[i]->findArea();
(假设该位置实际上已被填充)。
【讨论】:
【参考方案2】:您正在寻找的是多态性。这是 C++ 和其他面向对象语言的基本特性。
您可以声明一个名为 Shape
的基类,并从中继承您的 Square
和 Round
类。然后,只需在您选择的标准库容器中保存指向它的指针(或更好的智能指针)。
struct Shape
virtual size_t getArea() = 0;
;
struct Round : public Shape
virtual size_t getArea() /* return calc */
;
struct Square : public Shape
virtual size_t getArea() /* return calc */
;
main ()
auto round = std::static_pointer_cast<Shape>(std::make_shared<Round>());
auto square = std::static_pointer_cast<Shape>(std::make_shared<Square>());
std::vector<std::shared_ptr<Shape>> vec;
vec.push_back(round);
vec.push_back(square);
for (auto & x : vec)
cout << x->getArea() << endl;
关于您的评论:
我基本上想知道是否可以切换出调用了哪些版本的类。
您可以使用以下方法之一来实现:
RTTI:使用dynamic_cast<>
检查你持有的对象是否属于某种类型:
if (dynamic_cast<Round>(x.get()) != NULL)
// x is a Round
else if (dynamic_cast<Square>(x.get()) != NULL)
// x is a Square
在你的类中添加一个成员,根据类型对其进行初始化,然后简单地检查一下:
struct Shape
enum Type
Round,
Square
Type _type;
Type getType() return _type;
Shape(Type type) : _type(type)
[..]
struct Round : public Shape
Round() : Shape(Shape::Round)
[..]
;
// Check it later on using:
switch (x->getType())
case Round:
// use
break;
[..]
使用typeid()
。只要你的基类是多态的,它就会给你正确的类型信息:
if (typeid(*x) == typeid(Round))
// x is a Round
else if (typeid(*x) == typeid(Square))
// x is a Square
【讨论】:
如果你问我,if
/switch
on RTTI 或一些自定义类型信息值永远不是答案。关于虚函数的答案的第一部分就足够了;其余的,对我来说,很可能只会让那些还不了解多态性的用户混淆编写糟糕的代码。
@underscore_d,您能详细说明一下吗?
虚拟函数已经根据派生类的具体类型实现了不同行为的需求,同时在基类中保留了一个通用接口。忽略该语言非常有用的功能,而是使用条件来实现您自己的子类特定行为是没有意义的、丑陋的、难以维护的,并且需要基础知道其子类的细节,所以这是一种代码臭味。此外,您没有解释为什么当虚函数存在时OP需要将它们视为选项;也许答案是因为没有理由!以上是关于通用对象向量/数组,其中每个存储的对象都有不同的类的主要内容,如果未能解决你的问题,请参考以下文章