[C++基础]拷贝构造和重载


函数重载和默认参数,拷贝构造,符号重载

默认参数值

void fun(int a=12,char c='c')
{

}
//全部指定
void fun1(int a ,char c,float f==12.1)
{

}
部分指定,从右向左连续指定

函数调用,有默认值的参数可以不用传递实参

有默认值,传递实参回覆盖默认值

函数重载

同一作用域内:函数声明向下

函数名相同,参数个数或者类型不同

返回值不能作为函数重载的条件

当一个函数有两个形参,一个是默认参数,另一个函数重载也是两个形参,会造成调用不明确

拷贝构造

c++不允许拷贝构造函数传值参数

构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值

public:
    CStu()
    {
    CStu(const CStu& a)
    }

何时调用

1.创建对象并初始化为同类对象

CStu a;
1 CStu a1(a);
2 CStu a2=a;
3 CStu a3=CStu(a)
4 CStu *a3=new CStu(a)
5 a4=a//这个不会调用

2 程序生成对象副本

//1:将以个对象作为实参传递给一个非引用类型的形参,
  //对象以值传递的方式传入函数参数
void fun(CStu a1)//类外函数
  //调用
  fun(a)

调用过程:

(1)当对象a传入fun函数的形参时,会产生一个临时变量,我们把这个临时变量叫做a1;

(2)调用拷贝构造函数,把test的值赋给a1,类似于 Cstu a1(a)

(3)等fun函数执行完,析构掉a1对象

//2从一个返回类型为非引用类型的函数返回一个对象
// 对象以值传递的方式从函数返回
CStu fun()
  {
    CStu a ;
    return a;//返回值相当于一个临时变量,调用拷贝构造
  }
  //调用
  fun( )

调用过程:

(1)当执行到return时,产生一个临时变量XX

(2)调用拷贝构造函数把a的值赋给XX,有点像CStu XX(a)

(3)拷贝构造函数执行到最后,析构掉a局部变量

(4)fun函数执行完析构掉XX

拷贝初始化和直接初始化

拷贝初始化:把右边的运算对象拷贝到正在创建的对象中

直接初始化:使用普通的函数匹配来选择和我们提供参数最匹配的构造函数

情况

默认的复制构造函数,逐个复制非静态成员(浅复制)复制的是成员的值。

stcrpy_s(c,4,'abc')//4:元素个数

默认拷贝构造可以不写,执行的就是复制内容

CStu(const CStu &a)
{
    this->b=a.b;
    stcrpy_c(this->c,4,a.c)
    //必须写全复制内容
}

同一个类的多个对象,内存排布一样,地址不同

浅拷贝

int *a;
CStu()
{
    a=new int[2];//指针可以指向数组的首地址
    a[0]=1;
    a[1]=2;//数组别忘了在析构函数释放空间

}
//mian:
CStu st;
CStu st1=st;

程序会报错,原因如下:

浅拷贝只是将成员的值进行赋值,两个指针指向一个空间,销毁对象时,析构函数会释放两次,报错。解决方法利用深拷贝

深拷贝

对于对象中动态成员,就不能仅仅简单地赋值了,而应该重新动态分配空间

CStu(const CStu& b)
{
    this.a->new int[2]
    this.a[0]=b.a[0]
    this.a[1]=b.a[1]
}
    //mian:
CStu st;
CStu st1=st;

让st1有自己的空间

可以利用函数

mencpy(this.a,b.c,8)//8表示字节

还有一个方法明天试一下

    p = new int;    // 为新对象重新动态分配空间  
*p = *(r.p);  

指针成员要用深拷贝,不能直接赋值

返回值为引用

我们的重载运算符返回void、返回对象本身、返回对象引用都是可以的,并不是说一定要返回一个引用,只不过在不同的情况下需要不同的返回值。

主要是两个原因:

1.允许进行连续赋值

2.防止返回对象的时候调用拷贝构造函数和析构函数导致不必要的开销,降低赋值运算符的效率。

重载运算符返回地址

类内重载!!

int a=1;
double b=1.2;
int nerror = -1;
 void* operator [](int n)
  {
      switch(n)
      {
      case 0:
          return &a;
      case 1:
          return &b;
      }
      return &nerror;
  }
  //main
  cout<< st[1];//取出了a值得地址

  //如果要取出地址相对应的值,利用*取值
  cout<<*st[1];//报错,因为返回的void类型没有确定的大小

  cout<<*(double*)st[1];//取出相应的值

void* :通用类型指针,其他类型指针可以往它转换。

如果要对他赋值,也要有类型限制

*(double*)st[1]=14;
cout<<*(double*)st[1];

不推荐这样使用,还是推荐使用引用返回值

int& operator [](int n)

自加自减运算符

前置++:

int operator ++ (CStu& st)
{
    st.age+=1;
    return st.age;
}
//main
 CStu st;
 cout<<++st;

后置++:

int operator ++ (CStu& st,int n)//int n 理解成一个标记,有int n就是后置++
{
    int a=st.age;
    st.age+=1;
    return a;

}
//main
 CStu st;
 cout<<st++;

重载类型转换

operator int() const//不改变对象内容
{
    return a;
}

没有返回类型!!但是要写返回值

必须是类内定义;

赋值运算符

必须定义为成员函数

赋值运算符通常应该返回一个指向其左侧运算对象的引用