无法实例化抽象类:为什么模板参数(引用)导致这种情况
Cannot instantiate abstract class: Why is the template parameter (reference) causing this?
我在使用某些代码时遇到问题。
"bar":无法实例化抽象类
我(终于)能够在少量代码中重新创建错误。
struct SomeStruct
{
// ******
};
template <typename TIN, typename TOUT, typename TINDEX>
struct IFoo
{
public:
virtual void add(const TIN item) = 0; // <-- BAD
//virtual void add(const TOUT& item) = 0; // <-- GOOD
// ******
};
template <typename TVALUE, typename TINDEX>
struct Bar : IFoo<TVALUE &, TVALUE, TINDEX>
{
public:
void add(const TVALUE& item)
{
// ******
}
// ******
};
int main(int argc, char *argv[])
{
SomeStruct someStruct;
Bar<SomeStruct, int> bar = Bar<SomeStruct, int>();
bar.add(someStruct);
// ******
}
任何人都可以告知为什么使用带有模板参数的引用会导致这种情况吗?
这里的问题是,当您编写const TIN
并且TIN
是引用类型时,const
应用于引用而不是值类型。
这就是为什么你看到const TIN
和const TOUT&
不同的行为,即使你认为它们应该是相同的。
一个简单的解决方法是将const
添加到IFoo
实例化中的值类型:
struct Bar : IFoo<const TVALUE &, TVALUE, TINDEX>
// here ^^^^
您的问题可以追溯到函数签名等基本概念:函数签名/原型由函数名称、参数数量、参数数据类型和这些参数的出现顺序给出。
对于任何两个函数,如果上述任何一项不同,那么您正在处理两个不同的函数。
更确切地说,这两个代表两个不同的签名:
virtual void add(const TIN item) = 0;
virtual void add(const TOUT& item) = 0;
由于您只实现了派生类中的第二个,因此会出现错误。
我们可以进一步简化您的示例:
template <typename T>
struct IFoo {
virtual void add(const T item) = 0;
};
template <typename T>
struct Bar : IFoo<T&> {
void add(const T& item) { }
};
在Bar
中,您将item
作为const T
的参考。在 IFoo
中,您声明了一个纯虚方法,该方法对T
进行const
引用。但是所有的引用本质上都是const
的,所以这是多余的 - 它相当于只引用T
。
对于Bar<int>
- IFoo::add()
的签名是void add(int& )
,而Bar::add()
是void add(const int& )
。这些签名不匹配 - 因此Bar
仍然是一个抽象类。只是一个隐藏IFoo::add()
.
如果您有 C++11 编译器,则最好将 override
关键字添加到Bar::add()
,以便收到以下编译器错误:
main.cpp:15:10: error: 'void Bar<T>::add(const T&) [with T = int]' marked 'override', but does not override
void add(const T& ) override { }
^
相关文章:
- C++:在不中断共享的情况下通过引用传递共享 PTR?
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- 为什么或在什么情况下,你会将参数作为C++中的引用(或指针)传递给函数?
- 如何在不使用临时变量的情况下取消引用返回指针的函数的返回值?
- 删除对象(具有不同类型)的引用时会发生什么情况?
- 如何在开关的情况下使用右值引用
- 为什么 lambda nullptr 取消引用在这种情况下有效?
- 在不使用模板的情况下获取 std::array 引用
- 有没有办法在不使用命名空间 std 或前缀 std:: 的情况下引用 cout?
- 在没有引用传递资源的情况下,如何在java中简化这些代码
- Python在不引用类名的情况下调用类函数
- 为什么C++默认情况下不移动构造右值引用?
- 寻找有关为什么此C++代码在没有引用的情况下不起作用的解释
- 在这种情况下,如何返回对数组中元素的引用?
- 警告:返回对临时 - 奇怪情况的引用(对 Rvalue 的澄清)
- 在不中断引用的情况下移动静态库的 *.pdb 文件 - LNK4099
- 在 C++ 中取消引用字符串时会发生什么情况
- 使用按引用调用时,不能在没有对象的情况下调用成员函数 const
- 默认情况下C++数组作为参数引用
- -std=c++0x 导致在 boost 1.64 的情况下返回对临时的引用