我的意思是,我试图重载运算符<<在课堂内
像这样 class A {
public:
ostream &operator<<(ostream &os);// which doesnt work
private:
friend ostream &operator<<(ostream &os, const A& a); //Works
int i;
};
Definition
ostream &operator<<(ostream &os, const A& a) {
os<<a.i;
return os;
}
为什么我不能在特定于类的类中重载运算符?还是我错过了什么?或者我是愚蠢甚至以这样的方式思考?请指教。
答案 0 :(得分:19)
成员函数:
ostream &operator<<(ostream &os);
确实有效,但不适合您想要的情况。当您执行以下操作时将调用它:
A a;
a << std::cout;
即。对象是操作员的左侧。
答案 1 :(得分:18)
问题是,您的operator<<
会将ostream
作为第二个参数,而不是第一个参数。这样,您可以执行myObject << std::cout
,但它看起来不直观,并且由于operator<<
是左关联的,您将无法链接调用。
将运算符声明为朋友而不是成员函数的另一个好处是可以进行自动转换。这意味着,如果您的某个课程B
不是来自A
,而是拥有B(A const&)
构造函数,那么您仍然可以执行std::cout << my_b;
并拥有它转换为A
然后打印。
幸运的是,如果您愿意,可以在课堂上将operator<<
定义为朋友。您的代码可以写成
class A {
int i;
friend std::ostream& operator<<(std::ostream& o, A const& a) {
o << a.i;
return o;
}
};
为什么标准不允许您指定参数应该在哪一侧?让我们假装它,并添加left_of
和right_of
关键字来指定:
struct B;
struct A {
A left_of operator+(B const&) {
return *this;
}
};
struct B {
B right_of operator+(A const&) {
return *this;
}
};
我们A a; B b; f(a + b);
时会发生什么?每个类都有一个处理这种情况的运算符,这意味着我们无法决定。由于转换的可能性,看到尽可能多的运营商应该是朋友,不允许这种事情并不是一个大问题,并防止这种模糊。 (当然,你也可以定义一个成员运算符和一个自由运算符,这会导致一个非常类似的问题。)
顺便说一句,就像事情一样,你的friend operator<<
的定义并没有返回任何东西,这会弄乱链接。
答案 2 :(得分:1)
请记住,对于类的非静态成员函数,第一个参数是this指针。 因此,&#34;运营商的签名&lt;&lt;&#34;功能,编译后会变成:
ostream &operator<<(A *this, ostream &os);
当您执行以下操作时,这将起作用:
A obj;
obj << std::cout;
想想&#34; obj&#34;作为第一个参数和&#34; std :: cout&#34;作为运算符的第二个参数&#34;&lt;&lt;&#34;。
更好的超载方式&#34;&lt;&lt;&#34;是通过使用友元函数,因为这样可以使重载运算符关联。