使用模板对象进行操作

Operating with template objects

本文关键字:操作 对象      更新时间:2023-10-16

免责声明 我不允许使用 BOOST 或任何其他库,只能使用标准库。

在我的类Foo中,我有一个模板函数foo,它接受 2 个参数:指向对象的指针和指向此对象成员函数的指针。如您所见,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;
};

我的问题是:我如何存储Bar的对象,在foo中创建,以便我可以稍后迭代它们并调用指向对象成员函数的指针,如下所示:

(BarStorage[i].objPtr->*BarStorage[i].action)();

使用类型擦除

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);
};

然后只需致电myBars[x]->invoke();


在评论中回答问题。

怎么override明确表示您从基类中重写虚函数。这在这里并不是真正必要的,但被认为是良好的做法。有关更多详细信息,请参阅维基百科文章。

它是 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

如果您使用 vector<unique_ptr<BarBase>> ,则无需担心删除任何内容。当vectorFoo的生命结束时被销毁时,它会破坏它的元素 - unique_ptr会删除它包含在自己的析构函数中的内存。

这也是 C++11 功能 - 对标准库的补充。您不必使用它(但请确保最后删除所有内容(。

怎么auto与其将同一类型重复两次(Bar<Type> * bar = new Bar<Type>();(,只需使用它一次,让编译器根据初始值设定项的类型推断出变量的正确类型。它的行为完全相同,只是打字更少,看起来更好:)

也是 C++11 功能,自 v4.4 起在 GCC 中受支持。

为什么myBars[x]->invoke()做正确的事?因为invokeBarBase中被声明为虚拟的。这意味着执行的方法是根据myBars[x]的动态类型(执行期间的实际类型(而不是静态类型来选择的。有关深入说明,请参阅 Wiki。此机制的运行时开销很小,但在处理动态类型时无济于事。