由于超类(按值传递)导致重载构造函数调用不明确
Ambiguous call of overloaded constructor due to super class (pass by value)
我为GSL的某些部分编写了一个小的c++包装器,并遇到了以下难题(对我来说)。代码(简化到最基本的部分)如下:
#include <stdlib.h>
struct gsl_vector_view {};
class Vector : protected gsl_vector_view {
public:
Vector ( const Vector& original );
Vector ( const gsl_vector_view view );
};
class AutoVector : public Vector {
public:
explicit AutoVector ( const size_t dims );
};
void useVector ( const Vector b ) {}
void test () {
const AutoVector ov( 2 );
useVector( ov );
}
不能在GCC 4.4.5下编译g++ -c v.cpp但收益率
In function ‘void test()’:
19: error: call of overloaded ‘Vector(const AutoVector&)’ is ambiguous
7: note: candidates are: Vector::Vector(gsl_vector_view)
6: note: Vector::Vector(const Vector&)
19: error: initializing argument 1 of ‘void useVector(Vector)’
我很惊讶受保护的基类gsl_vector_view被useVector(Vector)的调用所考虑。我本以为useVector属于"c++编程语言"第3版第405页中所说的"一般公众",因此无法访问受保护的信息,因此不会被它混淆。我知道可以通过将构造函数声明为
来消除歧义 explicit Vector ( const gsl_vector_view view );
我不知道(老实说,也不理解)的是,当我将构造函数声明为
时,重载调用的模糊性就消失了。 Vector ( const gsl_vector_view& view );
。通过引用传递参数(无论如何我认为这样做是正确的)
重载解析是在访问检查之前完成的,这就是为什么即使是受保护的基类成员也要考虑。
重载解析在标准的13.3章中有描述。我的解释是,将const AutoVector ov
绑定到Vector ( const Vector& original );
是用户定义的转换,一种派生到基的转换([13.3.3.1.4/1])类型。对于Vector ( const gsl_vector_view view );
,转换顺序也是自定义转换,因为它是左值到右值的转换,然后是用户自定义转换。因此,两个转换序列被认为是相等的,没有一个比另一个好,因此你得到了歧义。
现在,如果您将变量更改为Vector ( const gsl_vector_view& view );
,那么这两个转换都是左值到值的转换,然后是用户定义的转换(派生到基的转换)。这两个可以排序([13.3.3.2/4]),转换为const Vector&
被认为更好,因此没有歧义。
这个问题与protected
继承或构造函数本身无关。对于普通的函数调用(无论继承是什么),这个问题也会持续存在。
当你在所有的重载版本中通过引用传递时,那么最接近的基类被选择(如果有超过一个基类是最接近的,那么它是病态的)。
在按值传递的情况下,所有的函数都被认为是同样好的候选函数。因此,您会得到这个编译错误。有一小段引自《标准》,在某种程度上符合你的问题。
§13.3.1 (5)
…声明的非静态成员函数reff限定符,一个额外的规则适用:-即使隐式对象形参不是const限定的,则可以将右值绑定到参数,只要在所有其他方面参数可以是转换为隐式对象形参的类型。
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- C++ 如何重载 [] 运算符并进行函数调用
- 错误:无法解析对重载函数的引用;你的意思是调用它吗?
- 对重载函数find_first_not_of的不明确调用
- 检查类是否具有可能重载的函数调用运算符
- 避免在人为的重载函数调用中拼写出类型
- 什么时候可以使用常量装饰调用我的重载函数?
- std::调用,未找到匹配的重载函数
- 为什么使用不匹配的参数调用重载函数仍然有效
- "fpclassify":对重载函数的不明确调用
- C++ 类的构造函数和函数调用运算符 () 重载之间的歧义
- C++编译时检查是否可以用某种类型的参数调用重载函数
- 重载函数调用编译时常量
- 为什么这些重载函数调用不明确
- 重载函数::调用哪一个
- 类中的重载函数调用运算符
- c++重载函数调用带有更多参数的自身版本
- 使用模板时C++ "const"神秘重载函数调用
- 重载函数调用操作符和赋值
- 从另一个操作符重载函数调用操作符重载函数:性能