【问题标题】:C++: Correctly overriding virtual function in template classC ++:正确覆盖模板类中的虚函数
【发布时间】:2014-02-06 01:22:48
【问题描述】:

考虑以下代码:

template<typename T>
struct MyTempl
{
    virtual void doStuff(const T &value) = 0;
};

struct MyImpl : MyTempl<int>
{
    void doStuff(const int &value) {}
};

struct MyPtrImpl : MyTempl<int*>
{
    void doStuff(const int* &value) {}
};

MyImpl imp1;
MyPtrImpl imp2;

这将无法正确编译:编译器告诉我MyPtrImpl 中的doStuff() 是纯虚拟的,即。我未能正确覆盖它。但是,如果我将int* 键入int_ptr 之类的东西,并将其用作MyPtrImpl 的模板参数,那么一切正常。

为什么没有typedef编译器无法推断出我的意图?

【问题讨论】:

    标签: c++ templates pointers reference virtual


    【解决方案1】:

    您没有指定正确的虚函数参数类型,因此您没有覆盖它。这会产生一个抽象类,因为虚函数是纯的。

    当指定 const 引用类型的参数时,如

    void doStuff(const int & value) {}
    

    其实是另一种写法

    void doStuff(int const & value) {}
    

    这应该被认为是声明常量引用的“正常”方式。从右到左阅读时,这意味着“对常量int 的引用”。将相同的模式应用于指针类型int* 会导致

    void doStuff(int* const & value) {}
    

    which compiles fine。但是不能按照上面的顺序写,因为这意味着不同的东西:从右到左读取const int* &amp;,你会得到“对指向常量int的指针的引用”。

    正如您所提到的,如果您使用 typedef 为指针类型 int* 起别名,则可以编写一个适用于上述顺序的替代方案:

    typedef int *T;
    void doStuff(const T & value) {}
    

    which also compiles fine,因为T 现在被视为单一文字类型,不会从上面引入歧义。换句话说,如何读取const T &amp; 的唯一选择是“对一个常量T 的引用,它本身就是一个指向int 的指针”。直观地理解它有点困难,但不可能将其理解为“对指向常量 int 的指针的引用”,因为这不会有 单个 T描述。

    如果您使用 C++11 编译器,我建议使用关键字 override 来检测此类问题(在某些情况下,此问题不会导致编译错误而是导致意外行为;例如,如果虚函数是纯的):

    void doStuff(int* const & value) override {}
    //                               ^^^^^^^^
    

    【讨论】:

    • ...这就是为什么constright 位置始终是正确的。 +1
    • @DavidRodríguez-dribeas 然而大多数人使用 left 版本。如果我没记错的话,包括标准规范中的大部分代码......
    • '从右到左读取const int* &amp;,你会得到“对指向常量 int 的指针的引用”。 - 这就是我需要知道的,谢谢!
    猜你喜欢
    • 2021-11-08
    • 2014-08-16
    • 2014-03-08
    • 2014-01-15
    • 1970-01-01
    • 2017-06-28
    • 2018-05-18
    • 2020-12-24
    • 1970-01-01
    相关资源
    最近更新 更多