介绍
PS:浅拷贝不适用于 动态数组赋值
拷贝构造中如果有 new 一个对象,建议采用深拷贝形式进行赋值; 详细参考文章:c++拷贝赋值 and C++拷贝赋值操作
无参构造
1.如果创建一个 类 没有写任何构造函数,则编译器会自动生成一个无参构造函数,定义内容为空
2.只要定义了 某一种构造函数,则系统不在自动生成 默认的构造函数
3.如果需要一个默认构造函数,则需要自己显示地写出来
参考源码
//默认无参构造函数
class A
{
A(){}
};
数据类型转换
数据类型转换构造 不需要 单参对应(PS: 单参 double 可以可以转换 int 类型变量)
例如:
1.声明样式:Complex(double real)
2.调用样式:Complex cp1 = 1.2;//隐式调用单参
或者Complex cp1(1.2);//显示调用单参
参考代码段
//类型转换构造
Complex cp1 = 1.2;//会隐式调用类型转换构造
cp1.print();
拷贝构造
例如:
1.声明样式:Complex(Complex& that);
2.调用样式:Complex cp2 = cp1;//隐式调用拷贝构造
或者Complex cp2(cp1);//显示调用拷贝构造
- (1).拷贝构造 注意事项
1.编译器会默认给一个空内容的 拷贝构造
(PS:如果提供了拷贝构造函数,则不在提供默认拷贝构造函数)
2.从相同类型的对象来构造对象(参数中 类型 要与 类名 相同)
3.拷贝构造 中有 数据溢出风险
4.拷贝构造 需要有 显示构造函数- (2).拷贝构造 作用(PS:拷贝后值一样,地址不一样)
1.用于根据一个已存在的对象复制出一个新的同类 类型对象
参考代码段
//拷贝构造
Complex cp2 = cp1;//会隐式调用拷贝构造
cp2.print();
浅拷贝
- (1).浅拷贝 注意事项
(PS:可以把浅拷贝当做一种BUG存在一样,无需主动释放)
1.当delete age 后 age2也会被delete掉,因为 age2 相当于继承了age中断结果图:
- (2).浅拷贝 作用(PS:拷贝后值一样,地址一样)
1.对内存地址的复制,让目标指针和源指针指向同块内存
2.通过其中一个指针去释放内存,其他指向改内存的指针会成为 野指针
错误代码段参考
Complex *age = new Complex(20);//显式调用单参构造重载
age->introduce();
Complex *age2 = new Complex(*age);//浅拷贝
age2->introduce();
delete age2;//当delete age后 age2也会被delete掉
深拷贝
- (1).深拷贝 作用(PS:拷贝 内存)
1.深拷贝会将整个内存都进行拷贝获取- (2).深拷贝 注意事项
1.需要开足够的空间进行拷贝获取
2.当有 double类型转换构造函数 还有 int类型转换构造函数 会形成 调用不明确
(PS:有可能会调用 int类型转换构造函数 也有可能 double类型转换构造函数 )
参考代码段
Complex *age = new Complex(20);//显式调用单参构造重载
age->introduce();
Complex *age2 = new Complex(*age);//浅拷贝
age2->introduce();
delete age;
age2->introduce();
源码
main.cpp
#include<iostream>
#include<string>
#include"Complex.h"
using namespace std;
void main()
{
//构造函数
#if 0
Complex*p_ca = new Complex;
p_ca->print();
delete p_ca;
#endif
//类型转换构造
#if 0
Complex cp1 = 1.2;//会隐式调用类型转换构造
cp1.print();
#endif
//拷贝构造(拷贝值和地址)
#if 0
Complex cp2 = cp1;//会隐式调用拷贝构造
cp2.print();
#endif
//浅拷贝(只拷贝地址)(PS:这段代码会报错)
#if 0
Complex *age = new Complex(20);//显式调用单参构造重载
age->introduce();
Complex *age2 = new Complex(*age);//浅拷贝
age2->introduce();
delete age2;//当delete age后 age2也会被delete掉
#endif
//深拷贝构造(拷贝内存)(PS:不能与类型转换构造同时使用,会造成调用错误)
#if 1
Complex *age = new Complex(20);//显式调用单参构造重载
age->introduce();
Complex *age2 = new Complex(*age);//浅拷贝
age2->introduce();
delete age;
age2->introduce();
#endif
system("pause");
}
Complex.h
#pragma once
class Complex
{
public:
//无参构造
Complex();
//单参构造,参数不是同类类型 叫类型转换构造函数
Complex(double real);
//单参构造,参数是同类类型 叫拷贝构造函数
Complex(const Complex& that);
//单参构造重载
explicit Complex(int age);//explicit防止隐式调用
//析构
~Complex();
public:
//声明函数print()
void print();
//声明函数introduce()
void introduce();
private:
double M_real;//实部
double M_vir; //虚部
int *M_pAge; //年龄
};
Complex.cpp
#include "Complex.h"
#include<iostream>
#include<string>
/**************************************************
此文件是Complex.h中的声明后需要定义的文件
1.用来写程序实现步骤
2.方便查看程序
(PS:如果只在Complex.h中声明 无定义则报错无法解析)
**************************************************/
using namespace std;
//无参构造
Complex::Complex()
{
M_real = 0;
M_pAge = NULL;
M_vir = 0;
cout << "无参构造" << endl;
}
//单参构造,参数不是同类类型 叫类型转换构造函数
Complex::Complex(double real)
{
M_real = real;
M_vir = 0;
cout << "类型转换构造" << endl;
}
//单参构造,参数是同类 类型 叫拷贝构造函数
Complex::Complex(const Complex& that)
{
M_real = that.M_real;
M_vir = that.M_vir;
浅拷贝
// M_pAge = that.M_pAge;//只复制地址
//深拷贝
M_pAge = new int(*(that.M_pAge));//开空间后赋值
cout << "拷贝构造" << endl;
}
//单参构造重载
Complex::Complex(int age)
{
cout << "单参构造重载" << endl;
if (age > 0)//判断所传入的值是否大于0
{
M_pAge = new int(age);//赋值
}
}
//打印复数
void Complex::print()
{
cout << M_real << "+" << M_vir << "i" << endl;
}
//打印年龄
void Complex::introduce()
{
cout << "My " << *M_pAge << " old years" << endl;
}
Complex::~Complex()
{
if (M_pAge !=NULL)
{
delete M_pAge;
M_pAge = NULL;
}
cout << "析构成功" << endl;
}