为何无法像调用成员函数operator+一样调用成员函数operator<<?
为什么
a1.operator<<(cout)会报错?我来帮你理清问题 首先得明确:你遇到的编译错误,核心原因是成员模板函数的参数推导失败,咱们一步步拆解来看:
问题根源:多余的模板参数导致推导失效
你写的operator<<是一个类模板成员函数,但这个模板参数T在函数的参数列表和函数体内完全没被用到——函数只有一个ostream&参数,和T没有任何关联。编译器没办法凭空猜出你要给T传递什么类型,所以直接调用a1.operator<<(cout)时,编译器就会因无法推导模板参数而报错。
对比一下能正常调用的operator+:它不是模板函数,参数和返回值都明确和类A绑定,编译器能直接定位到对应的函数,自然不会出问题。
解决方法:两种方案任选
1. 显式指定模板参数(临时救急,不推荐)
既然编译器猜不出T,那我们直接告诉它就行:
a1.operator<<<int>(cout); // 随便指定一个类型都可以,反正函数里没用到T
不过这种写法非常别扭,而且你的模板T本来就是多余的——完全没必要把operator<<搞成模板函数!
2. 去掉多余模板,改成普通成员函数(更合理)
既然T没被使用,直接把模板声明删掉,将operator<<改为普通成员函数:
class A { int x; public: A(int i = 0) { x = i; } A operator+(const A& a) { return x + a.x; } // 去掉template,改为普通成员函数声明 ostream& operator<<(ostream&); }; // 对应的实现也去掉template ostream& A::operator<<(ostream& o) { o << x; return o; }
这样再调用a1.operator<<(cout)就可以正常编译了,编译器能直接找到对应的成员函数。
额外建议:operator<<的常规写法
其实咱们平时用cout << a1这种习惯写法时,operator<<一般不会写成类的成员函数——因为成员函数的左操作数必须是类对象(也就是这里的a1),调用时就得写成a1 << cout,这和常规使用逻辑完全相反。
正确的常规写法是把operator<<写成全局友元函数,这样左操作数可以是ostream对象:
#include "pch.h" #include <iostream> using namespace std; class A { int x; public: A(int i = 0) { x = i; } A operator+(const A& a) { return x + a.x; } // 声明友元函数,让它能访问类的私有成员x friend ostream& operator<<(ostream& o, const A& a); }; // 实现友元函数 ostream& operator<<(ostream& o, const A& a) { o << a.x; return o; } int main() { A a1(33), a2(-21); a1.operator+(a2); cout << a1; // 这才是我们熟悉的用法 return 0; }
这种写法既符合日常使用习惯,代码逻辑也更直观。
内容的提问来源于stack exchange,提问作者Alin Catalin Preda
相关产品推荐
相关产品推荐

