【问题标题】:Member template functions cannot be virtual - workaround?成员模板函数不能是虚拟的 - 解决方法?
【发布时间】:2023-04-10 07:58:01
【问题描述】:

我了解为什么member template functions cannot be virtual,但我不确定最好的解决方法是什么。

我有一些类似的代码:

struct Entity
{
    template<typename It>
    virtual It GetChildren(It it) { return it; }
};

struct Person : public Entity
{
    template<typename It>
    virtual It GetChildren(It it) { *it++ = "Joe"; }
};

struct Node : public Entity
{
    Node left, right;
    const char *GetName() { return "dummy"; }

    template<typename It>
    virtual It GetChildren(It it)
    {
        *it++ = left.GetName();
        *it++ = right.GetName();
        return it;
    }
};

显然,我需要动态调度。但鉴于这些类实际上非常大,我不想模板化整个类。而且我仍然想支持任何类型的迭代器。

实现这一目标的最佳方法是什么?

【问题讨论】:

    标签: c++ virtual-functions member-functions


    【解决方案1】:

    如果支持任何类型的迭代器是您唯一想要的,您可以使用使用类型擦除的迭代器。我认为在 Boost Sandbox/Vault 或 Adob​​e Labs 或其中之一的某个地方实现了 any_iterator。这是来自 Google 的第一个结果:

    http://thbecker.net/free_software_utilities/type_erasure_for_cpp_iterators/any_iterator.html

    【讨论】:

    • 嗯...所以这几乎会创建一个双动态调度机制,一个用于类,一个用于迭代器?
    【解决方案2】:

    由于您不想模板化整个类,并且不想使用带有类型擦除的迭代器,唯一的解决方案是编写自己的迭代器。

    顺便说一句,你的例子看起来很奇怪。也许你可以看看如何改进设计,这会让你的问题消失。

    【讨论】:

    • +1 这无论如何都不是首选答案,但我想它会起作用。
    【解决方案3】:

    您不想笼统地“支持任何类型的迭代器”。

    您希望满足 STL 容器的要求,以提供用户可以普遍支持的迭代器。创建一个迭代器,然后为您的容器提供一个迭代器 typedef:

    class Entity_Iterator {
    public:
        Entity_Iterator operator++() { /* et cetera */ }
        Entity& operator*() const { /* et cetera */ }
    private:
        Entity* entity_ptr_;
        // et cetera
    }
    
    class Entity_Container {
    public:
        typedef Entity_Iterator iterator;
        iterator begin() const { /* et cetera */ }
        iterator end() const  { /* et cetera */ }
    private:
        Entity* head_;
        // et cetera
    }
    

    现在用户可以遵循 STL 容器约定来使用您的容器,并且您也可以将 STL 算法应用于您的容器:

    Entity_Container x;
    Entity_Container::iterator i = x.begin();
    i->GetName();
    

    编辑添加链接:

    http://www.sgi.com/tech/stl/Container.html

    编辑

    我正在尝试在 Google 上找到一个完整的 C++ 代码存根模板的链接,以实现我记得曾经见过的 STL 容器,但我发现 Google STL 模板非常困难。

    编辑

    这样做,您将能够将您的容器编写为一个树形结构,其中可以包含从具有虚拟方法的 Entity 继承的异构类型,这看起来就是您正在尝试做的事情?

    或许没有?

    【讨论】:

    • 我很困惑,这如何与多态性一起工作?例如,Entity::begin() 的返回值是多少?它不能是具体的iterator,因为类型将取决于Entity 的派生类型(因为不同的类有不同的方法来遍历它们的子类)。那么我需要返回某种指向迭代器的指针吗?
    • 考虑我创建的Entity_Iterator 存根:它有一个指向Entity 的指针。如果有一个虚拟的Entity::GetName() 函数,那么您可以通过迭代器引用的任何Entity 派生类型来调用它,参见上面的i-&gt;GetName()
    • 哦,问题是,没有一个虚拟的GetName() 函数——这正是我没有在Person 类中放入一个虚拟函数的原因例子。 (您可以修改示例以适应此设计的事实是无关紧要的......我只是用一些简单易懂的东西来说明问题,这并不意味着实际设计很容易“修复”作为例子..)
    • 我赞成 VJo 和 K-ballo 的答案,这比我的答案更好。
    猜你喜欢
    • 2011-02-25
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    相关资源
    最近更新 更多