关于C++的连续运算符重载

之前看mxnet,奇怪为什么可以写写成这个样子

load.add_attr("xxx",1)
    .get_add()
    .add_attr()
    .simplify()

cout<<"xxx"
    <<"ddd"
    <<"xxx"

后面我才明白,这些方法返回是这个类对象本身(return *this),所以可以一直用.来调用新的方法,或者重复调用一个方法

而流插入运算符也一样,cout是ostream类的一个对象,这个操作符返回的是ostream类本身,所以可以一直调用operator <<. 我们要看到它本质的函数调用形式是

> cout.operator<<(5).operator<<("xxx")

Demo& add_attr(){
   xxx
   return *this;
}

而流插入运算符是 5+c一样,成员函数不够用,要加要加到int类里面去,但这个类早就写好,现在是要加到我们写的复数类里面去,怎么办呢,只能加为全局函数,需要写出友元函数才够用

os.operator<<(Demo)demo里面可以写一个

friend ostream& operator<<(ostream& os, const Demo& c){

os<<c.real<<"+i"<<c.img;

return os;

}

今天还弄明白了,强制类型转换的本质函数调用关系是什么

(double)c   等价于 c.opeator double()

重载强制类型转换运算符:成员函数,单目运算,没有返回值和参数值

operator double(){return this->real;}

从设计者的角度去思考问题

object.operator++() --效率高的

++obj (返回修改后的值)

obj++ (返回修改前的值),看object在哪个未知,前还是后,来决定返回的是前还是后的值

这两种的本质函数调用关系都是obj.opeator++(),区分不出前置和后置,因此,编译器决定多写一个没用的int参数来区别。在实现的过程中,还可以发现哪一种实现效率低一些;要保留一个temo原值效率低一些。++i效率高一些。

然后我在实践的过程中有一个问题

class Demo
{
  public:
    int x;
    Demo( int n ) : x( n ) {}
    Demo operator++()
    // ++i
    {
        x += 1;
        return *this;
    }
    Demo& operator++( int )
    // i++ 为什么这个返回类型 不能加引用& ???
    {
        Demo tmp = *this;
        x += 1;
        return tmp;
    }
    friend ostream& operator<<( ostream& os, const Demo& c )
    {
        os << c.x << "\n";
        return os;
    }
};
int main()
{
    Demo d( 10 );
    cout << ( d++ ) << "\n";
    cout << d << "\n";
    return 0;
}

main.cpp:21:16: warning: reference to local variable 'tmp' returned [-Wreturn-local-addr]
   21 |         return tmp;

我不明白为什么这个返回类型不能是引用,编译的时候提示,引用一个函数内部的local variable是由问题的。

MOOC的课程老师讲解说,(++a)这种高效实现,返回的一个引用,结果可以放在等号左边,对其引用的对象进行赋值。

( ++a ) = 100;

依稀记得函数返回值引用可以这样用

func()=10;

我调查总结,什么情况下返回值是引用,什么情况下返回值不是应用。参数的话,如果内容要改变,就用引用,不改变加const, 返回如果希望可以连用,用于左值,需要用引用,这样可以进行赋值。

complex operator+(complex& a)

complex& operator++(){return *this}  (++a)=10;

complex& operator=(const complex& a){return *this} 本质原因是赋值运算符是可以连用的,所以返回引用 a=b="hello"   a.operator=(b.operator=("hello"))

### C++ 运算符重载的使用方法 C++ 中的运算符重载是一种允许为已有的运算符赋予新的含义的技术。它主要用于类类型的对象之间执行操作,使代码更具可读性和直观性。 #### 成员函数实现运算符重载 运算符重载可以通过类的成员函数或友元函数来实现。以下是一个通过成员函数实现加法运算符 (`+`) 的示例: ```cpp #include <iostream> using namespace std; class A { private: int x, y; public: A(int x1 = 0, int y1 = 0) { x = x1; y = y1; } // 重载 + 运算符 A operator+(const A& a) const { return A(x + a.x, y + a.y); // 返回一个临时对象作为结果 } void show() { cout << "x=" << x << ", y=" << y << endl; } }; int main() { A a1(1, 2); A a2(3, 4); A a = a1 + a2; // 使用重载的 + 运算符 a.show(); // 输出: x=4, y=6 return 0; } ``` 在上述代码中,`operator+` 是一个成员函数,它接受一个 `const A&` 类型的参数,并返回一个新的 `A` 对象。这个函数用于实现两个 `A` 类对象的加法操作 [^1]。 #### 友元函数实现运算符重载 另一种方式是使用友元函数进行运算符重载。这种方式更适合需要访问类私有成员的操作符(如流输出运算符 `<<`)。以下是一个示例: ```cpp #include <iostream> using namespace std; class A { private: int x, y; public: A(int x1 = 0, int y1 = 0) { x = x1; y = y1; } // 声明友元函数 friend A operator+(const A& a1, const A& a2); void show() { cout << "x=" << x << ", y=" << y << endl; } }; // 友元函数实现 + 运算符重载 A operator+(const A& a1, const A& a2) { return A(a1.x + a2.x, a1.y + a2.y); } int main() { A a1(1, 2); A a2(3, 4); A a = a1 + a2; // 使用友元函数重载的 + 运算符 a.show(); // 输出: x=4, y=6 return 0; } ``` 在这个例子中,`operator+` 被声明为类 `A` 的友元函数,并在类外部实现了该函数 [^1]。 --- ### C++ 运算符重载实现原理 运算符重载本质上是通过函数调用机制来实现的。当程序中使用了重载运算符时,编译器会根据运算符的类型和操作数的类型选择合适的函数进行调用。 #### 参数匹配与函数解析 C++ 编译器会根据操作数的类型和数量来决定调用哪个重载函数。例如,在 `a1 + a2` 中,如果 `a1` 和 `a2` 都是 `A` 类的对象,则编译器会选择 `A::operator+` 或者相应的友元函数 [^1]。 #### 返回值与临时对象 在重载运算符时,通常会返回一个新的对象作为结果。例如,在 `A(x + a.x, y + a.y)` 中,构造了一个临时对象并将其作为返回值。这种设计确保了运算符的链式调用(如 `a1 + a2 + a3`)能够正常工作 [^1]。 #### 限制与注意事项 - **不可重载运算符**:某些运算符不能被重载,例如作用域解析运算符 `::`、条件运算符 `?:` 等。 - **保持语义一致性**:重载运算符时应尽量保持其原有的语义,避免造成混淆。 - **效率问题**:频繁创建临时对象可能会影响性能,因此可以考虑使用引用或优化构造函数来减少开销 。 --- ### 示例:重载 `<<` 运算符以支持流输出 为了方便调试和输出信息,可以重载 `<<` 运算符以支持将自定义类的对象直接输出到流中: ```cpp #include <iostream> using namespace std; class A { private: int x, y; public: A(int x1 = 0, int y1 = 0) { x = x1; y = y1; } // 声明友元函数 friend ostream& operator<<(ostream& os, const A& a); }; // 重载 << 运算符 ostream& operator<<(ostream& os, const A& a) { os << "x=" << a.x << ", y=" << a.y; return os; } int main() { A a(5, 6); cout << a << endl; // 输出: x=5, y=6 return 0; } ``` 在这个例子中,`operator<<` 被重载为一个友元函数,使得 `cout << a` 可以直接输出对象的信息 [^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值