C++ 类(运算符重载(3))

文章概述

  1. 重载左移操作符和右移操作符
  2. 重载等号操作符

重载左移操作符和右移操作符

a. 我们首先知道<<,>>的顺序是从左往右执行的。

int a=2;
//cout<<a;  cout<<endl;
cout<<a<<endl;

b. 代码:重载<<运算符

class Test
{
    //friend void operator<<(ostream&out, Test& a); ostream&
    friend ostream& operator<<(ostream&out, Test& a);
private:
    int x;
public:
    Test()
    {
        x = 1;
        cout << "对象被创建" << endl;
    }
    ~Test()
    {
        cout << "对象被释放" << endl;
    }
};

//void operator<<(ostream&out,Test& a)
//{
//  cout << a.x << endl;
//}ostream&

ostream& operator<<(ostream&out,Test& a)
{
    cout << a.x << endl;
    return out;
}

int main()
{
    Test a;
    //int i=1; 由cout<<i<<endl;能不能将对象输出cout<<a<<endl;
    //需求:cout << a ; 通过需求写出函数声明: void operator << (ostream&out,Test& a)
    //1.通过友元函数实现需求:
    cout << a;
    //2. 因为成员函数cout.operator(Test&a),我们不能访问ostream类。这也就是友元函数的应用场景
    //3. 新的需求: cout<<a<<endl;<<运算符的顺序是从左往右执行的.即cout<<a应该有个返回值
    //   ostream& operator<<(ostream&out,Test& a)
    cout << a << "abc"<<endl;
    return 0;
}

c. 代码: 重载>>运算符

class Test
{
    friend istream& operator>>(istream&in, Test& a);
private:
    int x;
public:
    Test()
    {
        x = 1;
        cout << "对象被创建" << endl;
    }
    ~Test()
    {
        cout << "对象被释放" << endl;
    }
    void PrintF()
    {
        cout << this->x << endl;
    }
};

istream& operator>>(istream&in, Test& a)
{
    cin >> a.x;
    return in;
}

int main()
{
    Test a,b;
    cin >> a >>b;
    a.PrintF();
    b.PrintF();
    return 0;
}

重载等号操作符(赋值操作)

a. 类对象中只有普通变量时:

class Test
{

private:
    int x;
public:
    Test()
    {
        x = 1;
        cout << "对象被创建" << endl;
    }
    Test(int x)
    {
        this->x = x;
        cout << "对象被创建" << endl;
    }
    ~Test()
    {
        cout << "对象被释放" << endl;
    }
    void PrintF()
    {
        cout << this->x << endl;
    }
};

int main()
{
    Test a(5),b(8);
    //分析b=a 内存中发生了什么?
    b = a;

    return 0;
}

这里写图片描述
b. 类对象中有指针变量的时候:

class Test
{
private:
    int* p;
public:
    Test(int x)
    {
        this->p = new int(x);
        cout << "对象被创建" << endl;
    }
    ~Test()
    {
        if (p!=NULL)
        {
            delete p;
        }
        cout << "对象被释放" << endl;
    }
    int* getP()
    {
        return p;
    }
};

int main()
{
    Test a(5),b(8);
    //获得赋值前对象中指针的地址
    cout << a.getP() << endl;
    cout << b.getP() << endl;
    b = a;
    //获得赋值后对象中指针的地址
    cout << a.getP() << endl;
    cout << b.getP() << endl;
    //分析: 程序释放对象的时候会崩溃 ?why?
    return 0;
}

这里写图片描述


上面是执行默认的赋值操作,会出现问题。我们下面重载赋值运算符,达到深拷贝的目的。

class Test
{
private:
    int* p;
public:
    Test(int x)
    {
        this->p = new int(x);
        cout << "对象被创建" << endl;
    }
    ~Test()
    {
        if (p!=NULL)
        {
            delete p;
        }
        cout << "对象被释放" << endl;
    }
    int* getP()
    {
        return p;
    }
    //赋值运算符实现深拷贝
    Test& operator=(Test& a)
    {
        if (this->p!=NULL)
        {
            delete p;
        }
        p = new int(*a.p);
        return *this;
    }
};

//深拷贝和浅拷贝的区别: 深拷贝需要重新开辟内存空间 浅拷贝不需要重新开辟内存空间
//当类中有指针变量的时候,我们需要手动的写运算符重载(赋值),实现深拷贝
int main()
{
    Test a(5),b(8);
    //根据需求: b=a  得出声明: operator=(Test& a)
    b = a;
    return 0;
}

总结:

a. 友元函数重载运算符使用注意点:

  • 运算符的左右操作类型不同的时候我们使用友元函数重载运算符;
Test a;
a =a+25;
  • 友元函数没有this指针,所需的操作数都必须在参数列表中显示声明,所以很容易实现类型的转换
  • C++中不能用友元函数重载的运算符:
= [] () ->

b. 重载赋值运算符的步骤:

Test a,b;
b=a;
  • 首先释放b的内存
  • 根据a的内存大小为b重新开辟内存空间
  • 最后将指针b的内容给a

注意: (1). 函数返回值当左值的时候,必须返回引用;
(2). 不要返回一个临时变量的引用或者指针。

猜你喜欢

转载自blog.csdn.net/wue1206/article/details/81129103
今日推荐