请考虑以下代码:
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;
这将无法正确编译:编译器告诉我doStuff()
中的MyPtrImpl
是纯虚拟的,即。我未能正确覆盖它。但是,如果我将int*
类型设置为int_ptr
,并将其用作MyPtrImpl
的模板参数,那么一切都会成功。
为什么编译器在没有typedef的情况下无法扣除我的意图?
答案 0 :(得分:17)
您没有指定虚函数的正确参数类型,因此您没有覆盖它。这导致了一个抽象类,因为虚函数是纯粹的。
指定const引用类型的参数时,如
void doStuff(const int & value) {}
它实际上是写
的替代方案void doStuff(int const & value) {}
应该被认为是声明常量引用的“正常”方式。从右到左阅读时,这意味着“对常量int
的引用”。将相同的模式应用于指针类型int*
会导致
void doStuff(int* const & value) {}
which compiles fine。但是那个不能按照上面的顺序编写,因为这意味着不同的东西:从右到左阅读const int* &
,你得到“对常量int
的指针的引用”。
正如您所提到的,如果您使用typedef为指针类型int*
添加别名,则可以编写与上述订单一起使用的替代方法:
typedef int *T;
void doStuff(const T & value) {}
which also compiles fine,因为T
现在被视为单一文字类型,而不是从上面引入含糊之处。换句话说,如何阅读const T &
的唯一选择是“对const T
的引用,它本身就是指向int
的指针”。直觉上理解它有点困难,但不可能的是将其理解为“指向常量int
”的指针,因为这不会有单个 {{ 1}}在说明中。
如果你使用C ++ 11编译器来检测这样的问题,我建议使用关键字T
(在某些情况下,这个问题不会导致编译错误,而是会出现意外情况行为;例如,如果虚函数不纯>:
override