使用模板对象操作

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)

Fik*_*tik 5

使用类型擦除:

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的特性 - 标准库的补充.您不必使用它(但请确保在最后删除所有内容).

怎么了autoBar<Type> * bar = new Bar<Type>();只需使用一次,让编译器根据初始化程序的类型推断出正确的变量类型,而不是重复相同类型的两次().它的行为完全相同,只是打字更少,看起来更好:)

也是C++ 11的特性,自v4.4起在GCC中得到支持.

为什么myBars[x]->invoke()做对了?因为invoke在虚拟中声明了BarBase.这意味着执行的方法是基于动态类型(执行期间的实际类型)myBars[x]而非静态类型来选择的.有关深入解释,请参阅Wiki.使用此机制会产生较小的运行时开销,但在处理动态类型时无法提供帮助.