我正在研究一个带有矩阵的项目,我遇到了重载运算符的问题。
我已声明这些用户友好的输入/输出功能:
friend std::istream& operator>>(std::istream& is, MathMatrix& m); //keyboard input
friend std::ostream& operator<<(std::ostream& os, const MathMatrix& m); // screen output
friend std::ifstream& operator>>(std::ifstream& ifs, MathMatrix& m); // file input
friend std::ofstream& operator<<(std::ofstream& ofs, const MathMatrix& m); // file output
在定义它们中的最后一个时,在这段简单的代码中,我收到错误并且无法编译:
// file output
std::ofstream& operator<<(std::ofstream& ofs, const MathMatrix& m) {
//put matrix dimension in first line
ofs << m.n << std::endl;
//put data in third line
for (int i=0; i<m.n; i++) {
for (int j=0; j<m.n; j++) ofs << m(i,j) << " ";
ofs << std::endl;
}
return ofs;
}
错误位于ofs << m.n
(ofs << m(i,j)
中的类似错误)。它说:
const MathMatrix &m
Error: more than one operator "<<" matches these operands:
function "operator<<(std::ofstream &ofs, const MathMatrix &m)"
function "std::basic_ostream<_Elem, _Traits>::operator<<(int _Val) [with _Elem=char, _Traits=std::char_traits<char>]"
operand types are std::ofstream << const int
过了一段时间我觉得问题可能就是我有一个像MathMatrix
这样的MathMatrix (int n)
构造函数,所以编译器可能会尝试从int n
转换为MathMatrix(int n)
。我不明白为什么它会这样做,但这是我能想到的唯一解释,考虑到IDE给出的解释。
你能看到我错过的东西吗?你知道怎么解决吗?
答案 0 :(得分:2)
如果在您的类中有一个构造函数,其单个参数的类型与您的类不同,则它可用于隐式类型转换。为了防止你只需要明确标记该构造函数:
class MathMatrix {
public:
explicit MathMatrix( int m );
...
};
始终将单个参数构造函数标记为显式是个好主意(除非参数是相同的类类型,或者您确实需要这样的类型转换)
答案 1 :(得分:2)
重载决策中存在一个微妙之处,导致选择函数ofs << m.n
之间存在歧义。这是一个重现问题的简短示例:
struct Base
{
void operator<<(int);
};
struct Derived : Base
{
};
struct converter
{
converter(int);
};
void operator<<(Derived&, converter const&);
int main()
{
const int i = 42;
Derived d;
d << i;
}
首先,成员函数Base::operator<<
获取类型Base&
的附加参数,仅用于重载解析[over.match.funcs] / 2
候选函数集可以包含要针对同一参数列表解析的成员函数和非成员函数。因此,参数列表和参数列表在此异构集中是可比较的,成员函数被认为具有额外的参数,称为隐式对象参数,它表示已调用成员函数的对象。
由于成员函数(甚至在Derived
中继承)是Base
的成员函数,因此参数类型为Base&
,而不是Derived
;见/ 4。
因此我们比较
void operator<<(Base&, int); // #0
void operator<<(Derived&, converter const&); // #1
来电d << i
的参数属于Derived
(左值)和const int
。因此:
const int
到int
)const int
至int
,int
至converter
)转换1.1比转换2.1差,但转换1.2优于转换2.2。因此,电话不明确。
或者:
MathMatrix
显式operator<<(std::ostream&, MathMatrix const&)
,但std::ofstream
没有声明(这将使1.1等于1.2,因此重载#1会变得更好)std::ofstream
显式转换为基类std::ostream
(以与先前版本类似的方式帮助)using std::operator<<;