Kol*_*nya 1 c++ templates pointers function-pointers pointer-to-member
免责声明我不允许使用BOOST或任何其他库,只能使用标准版.
在我的类中,Foo我有一个模板函数foo,它有两个参数:指向对象的指针和指向此对象成员函数的指针.foo正如您所见,该函数适用于任何类的指针.我不知道,会传给哪一堂课.此函数创建模板结构的实例.
template <typename TypeName>
struct Bar
{
void(TypeName::*action)();
TypeName* objPtr;
};
template <typename TypeName> void Foo::foo ( void(TypeName::*action)() , TypeName* objPtr )
{
Bar <TypeName> bar;
bar.action = action;
bar.objPtr = objPtr;
};
Run Code Online (Sandbox Code Playgroud)
我的问题是:如何存储Bar,创建的对象foo,以便稍后我可以迭代它们并调用指针到对象成员函数,如下所示:
(BarStorage[i].objPtr->*BarStorage[i].action)();
Run Code Online (Sandbox Code Playgroud)
使用类型擦除:
class BarBase {
virtual void invoke() = 0;
};
template<typename TypeName>
class Bar final : public BarBase {
void(TypeName::*action)();
TypeName* objPtr;
virtual void invoke() override { (objPtr->*action)(); }
};
class Foo {
std::vector<std::unique_ptr<BarBase>> myBars;
/* ... */
};
template <typename TypeName>
void Foo::foo ( void(TypeName::*action)() , TypeName* objPtr)
{
auto bar = new Bar<TypeName>();
bar->action = action;
bar->objPtr = objPtr;
myBars.emplace_back(bar);
};
Run Code Online (Sandbox Code Playgroud)
然后简单地打电话 myBars[x]->invoke();
在评论中回答问题.
怎么了override?明确地说你从基类覆盖虚函数.这在这里并不是必需的,但被认为是一种很好的做法.有关详细信息,请参阅Wikipedia文章.
它是C++ 11的一个新功能,一些编译器长期以这种或那种方式支持这个功能,但它现在才被标准化.GCC应该从4.7版本支持此功能 - 您必须使用命令行参数-std=c++0x.
怎么了unique_ptr?它让生活更轻松.当你分配时new Bar<XXX>(),你必须在某个时候说delete要释放那个记忆.如果将指针放在资源管理对象中unique_ptr,则不再需要担心删除它.随着vector<BarBase*>你就必须申报析构函数Foo,做类似:
for each element in myBars
delete element
Run Code Online (Sandbox Code Playgroud)
如果您使用vector<unique_ptr<BarBase>>,则无需担心删除任何内容.当vector它在Foo生命结束时被摧毁时,它将破坏它的元素 - 并unique_ptr删除它在自己的析构函数中包含的内存.
这也是C++ 11的特性 - 标准库的补充.您不必使用它(但请确保在最后删除所有内容).
怎么了auto?Bar<Type> * bar = new Bar<Type>();只需使用一次,让编译器根据初始化程序的类型推断出正确的变量类型,而不是重复相同类型的两次().它的行为完全相同,只是打字更少,看起来更好:)
也是C++ 11的特性,自v4.4起在GCC中得到支持.
为什么myBars[x]->invoke()做对了?因为invoke在虚拟中声明了BarBase.这意味着执行的方法是基于动态类型(执行期间的实际类型)myBars[x]而非静态类型来选择的.有关深入解释,请参阅Wiki.使用此机制会产生较小的运行时开销,但在处理动态类型时无法提供帮助.