【问题标题】:Template method over non-template method in derived class派生类中的模板方法优于非模板方法
【发布时间】:2011-01-01 19:54:52
【问题描述】:
class A {
public:
    template<typename T> void func(size_t n, T values[]) { ... }
};

class B : public A {
public:
    void func(size_t n, uint32_t values[]) { ... }
};

为什么函数B::func()在调用这段代码时优先于函数模板A::func()

uint32_t values[5];
A* obj = new B();
obj->func(5, values);

【问题讨论】:

  • 因为重载解析规则选择最相等的类型匹配和最具体的匹配(在本例中为非模板匹配)。
  • Herb Sutter 的一些建议gotw.ca/gotw/049.htm
  • 不是作者的意图吗?
  • @peoro:是的,我想。在我错过了“不”之后,我重新措辞并发表了严厉的评论,解释说“不”缺少......

标签: c++ templates class derived


【解决方案1】:

两个原因-

  1. 在 C++ 中,仅当基类函数标记为虚拟时,成员函数才会覆盖基类成员函数。否则,C++ 将两者视为巧合同名的独立函数。这与 Java 形成鲜明对比,Java 中的函数以原子方式覆盖基类函数。

  2. 在 C++ 中,模板成员函数不能标记为虚拟。这部分是由于最常用的虚函数的实现 - vtables - 与 C++ 模板实例化系统相结合。 C++ 将同一模板在不同类型参数上的所有实例化视为单独的函数,并延迟生成这些实例化。这是 vtable 实现的一个问题,因为 vtable 需要在编译时静态确定类中不同虚函数的数量,以及对它们的排序。由于模板虚函数意味着类中虚函数的数量和顺序未知,因此 C++ 不允许这样做。

【讨论】:

  • re #2 另请参阅my answer 的常见问题解答条目。
  • 所以我的问题的唯一解决方案是在A中制作非模板版本的func(调用模板函数)并在B中覆盖它?
  • 应该可以。出于好奇,为什么你有一个模板成员函数可以生成任意类型的数据?
  • 这只是该功能的一个用例。
【解决方案2】:

如果您在 A 类型的对象/指针/引用上调用 func,则会调用 A::func,因为 func 不是虚拟的(也不能是:它是一个模板函数)。

你真的测试过你的代码吗?

【讨论】:

    【解决方案3】:

    A::func() 未声明为virtual,因此编译器不会生成虚拟表和在运行时调用B::func() 所需的任何其他代码。它与模板无关。

    【讨论】:

      【解决方案4】:

      因为 B::func 不是 A::func 的重载,而且无论你做什么都永远不可能。甚至不要尝试声明 A::func 虚拟,因为你不能。无论你想做什么,你都做不到。静态和动态多态性不能在 C++ 中混用。

      如果您的指针指向 B*,而不是 A*,您会期望调用它的版本。

      【讨论】:

        猜你喜欢
        • 2016-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-24
        • 2019-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多