首页 > 编程语言 >C++温故补缺(四):构造函数和复制构造函数

C++温故补缺(四):构造函数和复制构造函数

时间:2023-03-20 23:26:12浏览次数:33  
标签:box int tp C++ b1 b2 温故 构造函数

构造函数和复制构造函数

构造函数

对于需要传值的构造函数,如

class box{
    protected:
        int X;
        int Y;
        int Z;
    public:
        box(int,int,int);
};
box::box(int x,int y,int z){
    X=x;
    Y=y;
    Z=z;
}

可以使用初始化列表

box::box(int x,int y,int z):X(x),Y(y),Z(z){

}

在函数后加冒号,然后是成员变量名(形参名)的格式

复制构造函数

复制构造函数是用已经实例化的对象来初始化新的对象的函数

如:box b2(b1);,格式:classname (const classname &obj){}

参数一般都是引用类型&,不能是不同传值,用指针也能但会出错

const也可以不加,还可以有两个复制构造函数,一个是const的,一个非const

即使没有定义复制构造函数,也可以使用对象初始化新对象,因为编译器会自动生成默认的复制构造函数,如果自己定义了,则会覆盖默认的

实例:

class box{
    public:
        int a;
        int b;
        box(const box & c):a(c.a),b(c.b){}; 
};

复制构造函数被调用的三种情况:

  1. 当用一个对象去初始化另一个同类对象,会调用复制构造函数
box b2(b1);
box b2=b1;

注:第二条语句是初始化语句,不是赋值.赋值语句的左边是已经初始化的变量.

box b1,b2;
b2=b1;

像上面这样就不会调用赋值构造函数,因为b2已经初始化过了

  1. 作为函数的参数时,会调用复制构造函数
class box{
    ...
};
void func(box b){
    ...    
}
int main(){
    box b1;
    func(b1);
}
  1. 作为函数的返回值时也会调用复制构造函数
class box{
    ...
};
box func(){
    box b;
    ...
    return b;
}

关于为什么当类成员中含有指针类型成员且需要对其分配内存时,一定要有自定义的复制构造函数?

默认的复制构造函数实现的只是浅拷贝,即直接将原对象的数据成员值依次复制给新的对象中对应的数据成员,并没有给新对象分配另外的内存空间.这样就导致,如果对象的数据成员 是指针的话,两个指针实际指向同一块内存空间

所以,这样就需要我们自己定义复制构造函数,为指针分配新的内存

例如:

#include<iostream>
using namespace std;

typedef struct{
    int a;
}T,*TP;

class box{
    public:
        TP tp=(TP)malloc(sizeof(T));
        box(){};
};

int main(){
    box b1;
    b1.tp->a=21;
    box b2=b1;
    b2.tp->a=22;
    cout<<b1.tp->a;
}

类box中有一个TP指针,我们先初始化b1,并给b1的tp结构体中的变量a赋值21,然后复制一个b2,给b2中的结构体的变量a赋值22,再输出b1的变量值,就是看看对b2操作能否改变b1

结果:

说明了两个tp指向同一个内存地址

自定义复制构造函数深拷贝:

#include<iostream>
using namespace std;

typedef struct{
    int a;
}T,*TP;

class box{
    public:
        TP tp=(TP)malloc(sizeof(T));
        box(){};
        box(const box& b);
};

box::box(const box& b){
    free(tp);
    tp=(TP)malloc(sizeof(T));
    tp->a=b.tp->a;
}
int main(){
    box b1;
    b1.tp->a=21;
    box b2(b1);
    b2.tp->a=22;
    cout<<b1.tp->a;
}

重新给tp分配内存,再输出:

标签:box,int,tp,C++,b1,b2,温故,构造函数
From: https://www.cnblogs.com/Tenerome/p/cppreview4.html

相关文章

  • C++温故补缺(三):基本输入输出
    基本输入输出输出:cout<<输入:cin>>错误:cerr<<日志:clog<<在功能和调用上,cout,cerr和clog看上去无差别,cerr对象是非缓冲的,每个流插入到cerr后会立即输出,而clog......
  • C++温故补缺(二):lambda函数
    Lambda函数参考:CSDNC++11开始,提供了对匿名函数的支持,成为Lambda函数(表达式)通常,lambda函数用于封装传递给算法或异步方法的几行代码,对应不需要复用,且短小的函数,......
  • C++温故补缺(九):C++多态
    C++多态继承和派生当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态如:shape类被派生为两个类:Rectangle和Triangle#include<iostream>usingnamespacestd......
  • C++温故补缺(八):运算符重载和函数重载
    运算符重载和函数重载重载是c++多态性的一大体现,重载运算符是给运算符添加新的定义,使之前不能运算的对象变得可运算,且一般和运算符的意义相似.函数重载主要是同名函数......
  • C++温故补缺(七):;类的访问控制和继承
    类的访问控制和继承类的静态成员类的静态成员用关键字static修饰,类似静态变量或静态函数,也是有共享的概念类的静态变量:静态变量在类的所有对象中共享,不能再类的定......
  • C++温故补缺(六):友元函数、内联函数和this指针
    友元函数、内联函数和this指针友元函数友元函数是定义在类的外部,但有权访问类的所有私有(private)和保护(protectd)成员.友元函数的原型在类的定义中出现,但它并不是类......
  • C++温故补缺(十五):多线程
    多线程参考:CSDN,知乎传统C++(C++11之前)中并没有引入线程的概念,如果想要在C++中实现多线程,需要借助操作系统平台提供的API,如Linux的<pthread.h>,或windows下的<windows.......
  • C++温故补缺(十四):信号处理
    信号处理信号是由操作系统传给进程的中断,能够提前终止一个程序。在Unix,Linux,MacOS或Windows系统上,都可以通过Ctrl+C产生中断。下面是可以在程序中被捕获的信号,并且可......
  • C++温故补缺(十三):模板
    C++模板模板是泛型的基础,泛型编程就是一种独立于任何特殊类型的方式编写代码。模板就是创建泛型类或泛型函数的蓝图。STL库中的几个数据结构(vector,list,map等)以及算法......
  • C++温故补缺(十二):动态内存
    C++动态内存同C,C++中也是有堆和栈的概念。栈是函数内部声明的所有变量都所占用空间,堆是程序中未使用的内存,在程序运行期间可用于动态分配。同样也有alloc()分配内存,新增......