C++笔记(四)

1.友元函数与友元类
         (1)友元函数:有一个类A,有一个函数叫func(),如果将func


()设为类A的友元函数,则func()可以访问类A中所有的成员,包括私有成员。
     友元函数步骤:1.在类A的内部,先写上数func()的函数声明;
                   2.在函数声明前写上friend关键字。
     友元函数说明:1.友元函数不是类的内部成员函数,是外部成员函数;
                   2.友元函数的声明不受访问控制符的限制。
              friend Complex add(const Complex &a,const Complex 


&b);
         (2)友元类:如果类B是类A的友元类,则类B中所有成员函数都是A


的友元函数。
                      A向访问B的私有成员,就将A设为B的友元函数或者


友元类。
              friend class Student;
         (3)友元可以突破类的访问限制,访问类的私有成员---------破


坏了类的封装性,是一种很不友好的行为,正常情况下,不要轻易使用友元。
                       
2.运算符的重载
         (1)运算符重载:给运算符添加一种新的规则。
     运算符重载步骤:1.写出函数名:    operator + 要重载的运算符;
                     2.写出参数列表:  根据操作数的类型写出形参列表



                     3.返回值:        根据需要设置返回值。
              Complex add(const Complex &a,const Complex &b);
       =====  Complex operator+(const Complex &a,const Complex 


&b);


              c = add(a,b);
       =====  c = operator+(a,b);//== c = a + b;
         (2)c = c1 + 10;
              编译器不知道一个Complex对象和一个int变量怎样计算?
     -------> operator+(c1,10)
     =======> Complex operator+(const Complex &,int )
         (3)外部函数:通过友元的方式实现运算符重载(以上);
              内部函数:
                        Complex operator+(const Complex &b(或者


&a))//后面加const,就与外部函数一样了
                        c = c1.operator+(c2);//Complex operator


+(Complex *const this,const Complex &c2);
              运算符重载:内部和外部只能有一个。
         (4)运算符重载的限制
3.自增自减运算符
              A:前置 ++ --
                ++c1;


                a:外部函数
                 Complex & operator++(Complex &c)//不能加const,因


为要自加
                 {
                      ++c.a;
                      ++c.b;
                      
                      return c;
                 }
                 b:内部函数
                 Complex & operator++()
                 {
                      ++a;
                      ++b;
                      
                      return *this;
                 }
               B:后置 ++ --
                 后置++,有一个int型的占位参数进行区分。
                 c1++;


                 a:外部函数
                   Complex operator++(Complex &c,int)//不要&,因为


局部变量,不能返回引用
                   {
                         Complex tep(c.a,c.b);//加tep,主要是因为在


c = c1++ + c2时可以先运算,再自加
                         c.a++;
                         c.b++;
          
                         return tep;
                   }
                  b:内部函数
                    Complex operator++(int)
                    {
                         Complex tep(a,b);
                         a++;
                         b++;
  
                         return *this;
                    } 
  


4,左移,右移运算符
          (1)左移操作符
                 A: 外部函数
                  a:cout << c;
                    void(改为ostream &) operator<<(ostream & 


out,const Complex &c)
                    {
                        out << c.a << "+" << c.b << "i";
                      或printf("%d + %di",a.c,c.b);


                        (加return out;)
                    }


                  b:cout << c << endl;//operator((operator<<


(cout,c)),endl)
                    cout << endl;    //operator(cout,endl)
                ===>ostream & operator<<(ostream & out,ostream & 


endl);
                B:外部函数
                   ostream & operator<<(const Complex &c)去掉out


用this代替。需要将其放在ostream类中。
                   左移运算符无法进行内部重载(因为istream 类,头文


件等不能修改),只能进行外部重载,通过友元的方式
                C:友元何时使用:无法操作左操作数的时候
                  不能用友元进行重载的操作符:= () [] ->


5.赋值运算符
          (1)默认赋值运算符,做的是浅拷贝
               Student s3;
               S3 = s;
          (2)自己重载赋值运算符
               A:Student s3 = s;
                  operator=(s3,s);(= 不能用全局进行重载,只能进行


内部重载)
       ======>    operator=(s);
       ======>    Student & operator=(const Student &s)
                  {
                      if(this == &s)//1.判断是否是自己
                      {
                          return *this;
                      }
                      
                      ifs.name== NULL)
                      {
                          delete [] name;
                          this->name = NULL;
                          id = s.id;
                          return *this;
                      
                      delete [] name;//2.释放原有空间
                      thid->name = new char[20];//3.开辟新空间
                      this->id = s.id;//4.复制
                      strpy(this->name,s.name);
                      return *this;
                  }//2.3.是为了防止内存泄露
               B:Student & operator=(const Student &s)
                  {
                      if(this != &s)//1.判断是否是自己
                      {
                          (//防止释放掉后,空间开辟未成功,在这可以


定义一个临时对象)
                          Student tep = s;//调用拷贝构造函数
                          //空间的交换
                          char *p = this->name;
                          this->name = tep.name;//新空间的地址
                          tep.name = p;


                          this->id = s.id;   
                      }
                      return *this;
                  }
                 
               C:char *p = NULL;
                 free(p);
                 free(p);
                 指针指向NULL,可以重复释放,不会出现问题


6.其他运算符
          (1)()函数调用运算符
                Test t(10);
                t();//()是运算符,函数调用运算符,函数对象,仿函数
          (2) && ||
               A: int a = 1;
                  int b = 0;
                  int c = 7;
                  b && (a = c);//b = 0 短路运算(不会执行)
                  a || (b = c);//a = 1 短路运算(不会执行)
               B: A a1 = 1;
                  A b1 = 0;
                  A c1 = 7;
                  b1 && (a1 = c1)//&&运算符重载本质上是函数调用,所


以不具备逻辑运算符的短路功能
          (3)数组下标运算符
#include <iostream>
using namespace std;
class Array
{
friend ostream& operator<<(ostream &out,Array &a);
public:
Array(int len)
{
if(len <= 0)
{
this->len = 0;
this->m_p = NULL;
}
this->len = len;
this->m_p = new int[this->len];
}
Array(const Array &a)
{
if(a.len == 0)
{
this->len = 0;
this->m_p = NULL;
}
else
{
this->len = len;
m_p = new int[this->len];
for(int i = 0;i < len;i++)
{
m_p[i] = a.m_p[i];
}
}
}
~Array()
{
if(m_p != NULL)
delete[] m_p;
m_p = NULL;
this->len = 0;
}


int getlen()
{
return len;
}


Array& operator=(const Array &a)
{
if(this != &a)
{  
Array temp = a;
int *p = this->m_p;
this->m_p = temp.m_p;
temp.m_p = p;


this->len = a.len;
}
return *this;
}
int& operator[](int index)
{
return m_p[index];
}


private:
int len;
int *m_p;
};


ostream& operator<<(ostream &out, Array &a)
{
for(int i = 0;i < a.len;i++)
{
out << a[i] << " ";
}
return out;
}


int main()
{
Array a(10);
for(int i = 0;i < a.getlen();i++)
{
a[i] = i;
}
cout << a << endl;
return 0;
}             
                  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值