运算符重载和友元函数

本文介绍了C++中的类定义,包括私有和公共成员的概念,以及构造函数和析构函数的作用。类的接口由公共成员函数构成,而友元函数允许非成员函数访问类的私有成员。还讨论了运算符重载,特别是如何通过成员函数和友元函数来实现,以及在某些运算符如<<上的应用和区别。
摘要由CSDN通过智能技术生成

类的结构

c++中使用class定义一个类,类中的数据与函数默认是私有的(private),同时可以将一部分的数据定义为公有的(public),私有部分的数据/函数只能被类中的函数访问,公有部分的内容可以被整个类的作用域访问,公有的成员函数被称为接口,成员函数在类中声明,在类外定义函数体。

以下是一个最简单的类,后续所有操作将在这个类的基础上扩展

#include<ostream>
#include<istream>         
using std::osstream;
class sock
{
private:
    int a;
    int b;
public:
    sock();                //构造函数的名称与类名相同
    sock(int c, int d);
    ~sock();              //析构函数
}

sock::sock()               //默认构造函数(在自定义构造函数时,必须自己提供默认构造函数)构造函数没有返回值类型
{
}

sock::sock(int c, int d)        //自定义构造函数(未定义构造函数的时候将会自动提供一个默认构造函数)
{
    a = c;
    b = d;
}

sock::~sock()
//析构函数(函数体通常为空)注意析构函数和销毁类的因果关系,在销毁类的时候调用析构函数,而不是调用析构函数导致类被销毁。
{
    cout << "ok" << std::endl;  //已经在头文件中暴露了ostream
}

void sock::show()
{
    cout << a << std::endl;
    cout << b << std::endl;
}

友元函数

类中的函数允许访问私有成员,但是在某些时候需要对接口进行扩展,也需要对类的私有成员进行访问,基于这种思想,在c++中出现了一类函数,函数本身不是类的成员函数,但是可以直接访问类的私有对象。

友元函数需要通过在函数前加friend定义,同时友元函数在类中定义

对上面的类进行扩展加入友元函数

#include<ostream>
#include<istream>         
using std::osstream;
class sock
{
private:
    int a;
    int b;
public:
    sock();                //构造函数的名称与类名相同
    sock(int c, int d);
    ~sock();              //析构函数
    firend void sum(const sock& a);
}

sock::sock()               //默认构造函数(在自定义构造函数时,必须自己提供默认构造函数)构造函数没有返回值类型
{
}

sock::sock(int c, int d)        //自定义构造函数(未定义构造函数的时候将会自动提供一个默认构造函数)
{
    a = c;
    b = d;
}

sock::~sock()
//析构函数(函数体通常为空)注意析构函数和销毁类的因果关系,在销毁类的时候调用析构函数,而不是调用析构函数导致类被销毁。
{
    cout << "ok" << std::endl;  //已经在头文件中暴露了ostream
}

void sock::show()
{
    cout << a << std::endl;
    cout << b << std::endl;
}

void sum(const sock& a)
{
    int sum;
    sum=a.a+a.b;
    cout<<sum<<endl;
}

成员函数和友元函数的异同

相同点:

成员函数和非成员函数都需要在类中定义,同时都可以访问这个类的私有对象。

不同点:

  1. 在类外定义函数体时成员需要使用域名运算符进行定义

  1. 成员函数使用时由类运算符(.)调用,友元函数直接使用

  1. 成员函数实际上隐式调用了当前类(即含有this指针),友元函数没有这个功能

#include<ostream>
#include<istream>         
using std::osstream;
class sock
{
private:
    int a;
    int b;
public:
    sock();                //构造函数的名称与类名相同
    sock(int c, int d);
    ~sock();              //析构函数
    firend void sum(const sock& a);
}

sock::sock()               //默认构造函数(在自定义构造函数时,必须自己提供默认构造函数)构造函数没有返回值类型
{
}

sock::sock(int c, int d)        //自定义构造函数(未定义构造函数的时候将会自动提供一个默认构造函数)
{
    a = c;                     //这里实际上可以理解为this->a=c;,即隐式调用当前对象
    b = d;
}

sock::~sock()
//析构函数(函数体通常为空)注意析构函数和销毁类的因果关系,在销毁类的时候调用析构函数,而不是调用析构函数导致类被销毁。
{
    cout << "ok" << std::endl;  //已经在头文件中暴露了ostream
}

void sock::show()
{
    cout << a << std::endl;
    cout << b << std::endl;
}

void sum(const sock& a)
{
    int sum;
    sum=a.a+a.b;              //友元函数必须显示的使用对象
    cout<<sum<<endl;
}

运算符重载与友元函数

运算符重载

c++中

多态的一种,及运算符的多态

运算符多态的核心在于重新对运算符定义,给予运算符不同的含含义,使用运算符重载来代替一部分函数。

重载运算符使用operate定义

#include<ostream>
#include<istream>         
using std::osstream;
class sock
{
private:
    int a;
    int b;
public:
    sock();                //构造函数的名称与类名相同
    sock(int c, int d);
    ~sock();              //析构函数
    firend void sum(const sock& a);
    sock operate+(const sock& a);
    friend sock operate+(const sock& a,const sock& b);
}

sock::sock()               //默认构造函数(在自定义构造函数时,必须自己提供默认构造函数)构造函数没有返回值类型
{
}

sock::sock(int c, int d)        //自定义构造函数(未定义构造函数的时候将会自动提供一个默认构造函数)
{
    a = c;                     //这里实际上可以理解为this->a=c;,即隐式调用当前对象
    b = d;
}

sock::~sock()
//析构函数(函数体通常为空)注意析构函数和销毁类的因果关系,在销毁类的时候调用析构函数,而不是调用析构函数导致类被销毁。
{
    cout << "ok" << std::endl;  //已经在头文件中暴露了ostream
}

void sock::show()
{
    cout << a << std::endl;
    cout << b << std::endl;
}

void sum(const sock& a)        //友元函数
{
    int sum;
    sum=a.a+a.b;              //友元函数必须显示的使用对象
    cout<<sum<<endl;
}

sock sock::operate+(sock& a)     //运算符重载算成员函数
{
    sock c;
    c.a=a+a.a;
    c.b=b+a.b;
    return c;                   
}
sock sock::operate+(sock& a,sock& b)     //运算符重载友元函数
{
    sock c;
    c.a=b.a+a.a;
    c.b=b.b+a.b;
    return c;                   
}

在使用成员函数作为重载函数时我们在使用过程中看如下代码

int main()
{
    sock a=(1,2);
    sock b=(2,3);
    sock c;
    c=a+b;      //在这里实际上可以理解为a.operate+(b),即a作为左值,b作为参数表传入     
}

在加法中大部分时候这两张没有很大的区别,但是对于某些运算符号将会出现一些问题

<<运算符的重载

#include<ostream>
#include<istream>         
using std::ostream;
class sock
{
private:
    int a;
    int b;
public:
    sock();                //构造函数的名称与类名相同
    sock(int c, int d);
    ~sock();              //析构函数
    firend void sum(const sock& a);
    sock operate<<(ostream& a);
    friend sock operate+(const sock& a,ostream os);
}

sock::sock()               //默认构造函数(在自定义构造函数时,必须自己提供默认构造函数)构造函数没有返回值类型
{
}

sock::sock(int c, int d)        //自定义构造函数(未定义构造函数的时候将会自动提供一个默认构造函数)
{
    a = c;                     //这里实际上可以理解为this->a=c;,即隐式调用当前对象
    b = d;
}

sock::~sock()
//析构函数(函数体通常为空)注意析构函数和销毁类的因果关系,在销毁类的时候调用析构函数,而不是调用析构函数导致类被销毁。
{
    cout << "ok" << std::endl;  //已经在头文件中暴露了ostream
}

void sock::show()
{
    cout << a << std::endl;
    cout << b << std::endl;
}

void sum(const sock& a)        //友元函数
{
    int sum;
    sum=a.a+a.b;              //友元函数必须显示的使用对象
    cout<<sum<<endl;
}

void operator<<(sock& s, std::ostream& os)   //友元函数重载
{
    os << s.a << std::endl << s.b;
}

void operator<<(std::ostream& os)   //成员函数重载
{
    os << a << std::endl << b;
}

注意使用成员函数和友元函数在<<重载的区别

注意在使用中的区别

int main()
{
   sock a=(1,2);
   a<<std::cout;             //由于成员函数相当于a.operate<<(std::ostream os)
   cout<<a;                  //友元函数定义的(习惯性写法)
}

即友元函数可以直接使用交换律等(但是这里要注意一个很重要的事情如下程序展示)

int operator+(int a,char b);  //函数一
int operator+(char b,int a);  //函数二

/*这两个 函数在c++中被认为是不一样的*/
//看下面两个加法式

int a;
char b;
int c;
c=a+b;    //调用函数一
c=b+a;    //调用函数二
//即以上说明了只有友元函数才能实现交换率,同时要实现交换率要同时创建两个运算符重载函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值