避免强制转换容器的元素指针类型
avoid to cast element pointer type of a container
我有一个函数,其中我需要指向Base
和Derived
类型的指针向量。我有一个函数,它应该能够处理这两种容器类型,因为它只调用所有在Base
中定义的虚拟函数。
如果给定元素指针,直接是没有问题的,比如:
void Func(Base*);
Derived* d;
Func(d); // works perfect
但如果有一个集装箱类型,它就会变得丑陋而危险。如果且仅当容器类型对两种指针类型都完全等效时,强制转换才会起作用。这通常是真的,因为所有已知的标准容器实现都实现了从void*
派生的指针类型,以最大限度地减少占用空间。
#include <iostream>
#include <vector>
class Base
{
public: virtual void Func() {std::cout << "Base" << std::endl; }
};
class Derived: public Base
{
public:
void Func() override { std::cout << "Derived" << std::endl; }
void MoreFunc(){ std::cout << "SomeMoreFunc" << std::endl; }
};
// This function should "eat" also vector<Derived*>
// this can be simply done by using templates,
// but results in doubling the code in memory while
// two instances will be created with exact the same
// content and they will not be optimized away ( gcc ).
void DoSomething( std::vector<Base*>& vec )
{
for ( auto& el: vec ) { el->Func();}
}
int main()
{
std::vector< Base*> vecBase;
vecBase.push_back( new Base );
vecBase.push_back( new Base );
std::vector< Derived*> vecDerived;
vecDerived.push_back( new Derived );
vecDerived.push_back( new Derived );
DoSomething( vecBase );
DoSomething( (std::vector<Base*>&)vecDerived ); // that cast I want to avoid!
for ( auto& el: vecDerived ) { el->MoreFunc(); }
}
如何避免向量元素类型的错误转换?做一个完整的容器副本是一种选择,但也浪费代码和运行时间。
对于这些问题,有"典型"的解决方案吗?
是的,DoSomething内部更为复杂,正如这个最小的例子所给出的那样。因此,简单地将for()删除到foreach/lambda是没有机会的,而且从外部调用DoSomething内部的函数也不适合我在这里遇到的现实问题。而且必须记住,for_each本身将在这里生成更多的模板实例,这与我想要避免的恰恰相反。
您可以使用<algorithm>
中的std::for_each
和lambda来实现这一点:
auto func = [](Base *ptr) { ptr->Func(); };
std::for_each(vecBase.begin(), vecBase.end(), func);
std::for_each(vecDerived.begin(), vecDerived.end(), func);
或者如下定义您的功能:
void DoSomething(Base* ptr) {
ptr->Func();
}
并与std::for_each
:一起使用
std::for_each(vecBase.begin(), vecBase.end(), DoSomething);
std::for_each(vecDerived.begin(), vecDerived.end(), DoSomething);
在这两种情况下都没有模板
老实说,代码中没有模板。std::for_each
是一个函数模板,但DoSomething
不会。不确定这是你想要的。
评论后编辑
避免模板的最好方法是从DoSomething
中获得循环
在这种情况下,任何接受Base *
的函数都可以
另一方面,如果你想在函数中迭代,你可能无法通过传递一个容器(模板)、传递两个迭代器(模板)或基于假设进行花式转换(有风险)。
请注意,向量的成员函数data
返回指向底层数组的指针。如果与size
结合使用,您将拥有对元素进行迭代所需的所有内容
无论如何,在您的情况下,Base **
和Derived **
是不同的野兽,您不能简单地将Derived **
传递给接受Base **
的函数。
任何使用标准库中函数的尝试(例如std::for_each
)都可能以某种方式使用模板函数而告终。
这是因为std::vector<Base *>
和std::vector<Derived *>
是不同的类型。
- 调整大小后指向元素值的指针unordered_map有效?
- 当该数组的索引中没有元素时,指针指向什么?
- 如何在基类指针向量的元素上应用重载的多态函数
- C++:添加新结构时,结构指针向量中的所有元素都会更新
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- 删除指针数组 (C++) 中的元素
- 从指向结构数组的指针中提取元素
- 指向数组基址的指针而不是指向第一个元素的指针有什么优点?
- 获取指向指针的指针元素 (c++)
- 经过最后一个数组元素末尾的指针是否应该等于超过整个数组末尾的指针?
- 存储指向动态数组元素的指针
- 通过作为指向 C++ 函数的指针传递来访问 std::array 元素的正确方法是什么?
- 如何使用指针C++将元素从2D数组复制到1D数组
- 如何将元素插入到标准::地图的共享指针中?
- C++通过别名指针以静默方式将错误的类型分配给数组元素
- 在删除之前更新一组元素指针中的元素
- 从 BST 中删除元素(指针错误)
- 避免强制转换容器的元素指针类型
- 填充一个无序的vector元素指针队列
- OpenCV元素指针如何存在于Obj-C类中