C++的构造函数、析构函数、拷贝构造函数等代码实例讲解
- 作者: 公交车上玩车震
- 来源: 51数据库
- 2021-08-06
c++的构造函数、析构函数、拷贝构造函数等代码实例讲解
#define _crt_secure_no_warnings #include #include
#include
#include
//指针指存储的是变量的内存地址
//引用是变量的别名
using namespace std;
/*
struct teacher{
char* name;
int age;
};
//引用
void my_print(teacher& t){
cout << t.name << t.age << endl;
}
//指针
void my_print2(teacher* t){
cout << t->name << t->age << endl;
}
//引用的主要作用就是作为参数或者返回值
void main(){
struct teacher t;
t.name = "tom";
t.age = 20;
my_print(t);
my_print2(&t);
system("pause");
}
*/
//指针引用,可以代替二级指针
/*struct teacher{
char* name;
int age;
};
void print(teacher** t){
teacher* tm = (teacher*)malloc(sizeof(teacher));
tm->age = 20;
*t = tm;
}
void print2(teacher* &t){
t = (teacher*)malloc(sizeof(teacher));
t->age = 20;
}
void main(){
teacher* t=null;
//print(&t);
print2(t);
cout << t->age << endl;
system("pause");
}*/
//指针常量,常量指针
/*void main(){
//如 0x0011(4) 0x0022(5)
int a = 4, b = 5;
//指针常量,不能改变地址的指针,但是可以修改它指向的内容
//0xff00(0x0011)
int* const p1 = &a;
//不能将0x0011修改为0x0022
//p1 = &b;会报错
*p1 = 5;
//常量指针,指向常量的指针,内容不能修改
//0xff00(0x0011)
const int* p2 = &a;
//可以将0x0011修改为0x0022
p2 = &b;
//这里会报错
//*p2 = 6;
cout << a << endl;
system("pause");
}*/
//1.单纯给变量取别名没有任何意义,作为函数参数传递,能保证参数传递过程中不产生副本
//2.引用可以直接操作变量,指针要通过取值(*p),间接操作变量,指针的可读性差
//常引用,类似于java中的final
/*void print(const int& a){
cout << a << endl;
}
void main(){
int a = 4, b = 8;
const int &c = a;
const int &d = b;
//这句话会报错,提示c不是一个可以修改的值
//c = d;
print(c);
system("pause");
}*/
//引用的大小
/*struct teacher{
char* name;
int age;
};
void main(){
teacher t;
t.age = 10;
//引用是变量地址的别名
teacher & tt = t;
teacher* tp = &t;
cout << sizeof(tt) << endl;//8
cout << sizeof(tp) << endl;//4
system("pause");
}*/
/*struct teacher{
char* name;
int age;
};
void print(teacher * t){
cout << t->name << "," << t->age << endl;
}
void print2(teacher& t){
cout << t.name << t.age << endl;
}
void main(){
//这个就相当于0x0011((null的地址)
teacher *t1 = null;
//这里不报错,就是说,传入的指针可能为null
print(t1);
//这里会报错,就是说,传入的引用的值不能为null,可以在传入前进行判断
//teacher &t2 = null;
//print2(t2);
}*/
//函数的默认参数
//在有默认值的后面的参数必须有默认值
/*void print(int a, int b = 6, int c = 9){
cout << a << "," << b << "," << c << endl;
}
//函数的重载
void print(int a, bool is_good){
cout << a << "," << is_good << endl;
}
void main(){
//print(20);
print(20, false);
system("pause");
}
*/
//可变参数
//要想使用可变参数,必须至少有两个参数。
/*void func(int i, int ...){
//读取 依赖stdarg.h
//可变参数指针
va_list args_p;
//开始读取可变参数,第一个参数为va_lsit,第二个参数为i
va_start(args_p,i);
//获取可变参数的值
//这个读取的是从第二个参数开始的
int a=va_arg(args_p, int);
int b = va_arg(args_p, int);
int c = va_arg(args_p, int);
cout << i<<","<
//循环读取
//第一个参数为后面可变参数的数量
/*void func(int count, ...)
{
va_list ap; //声明一个va_list变量
va_start(ap, count); //第二个参数表示形参的个数
int sum = 0;
for (int i = 0; i < count; i++) {
int value=va_arg(ap, int);//第二个参数表示形参类型
cout << value << endl;
}
va_end(ap); //用于清理
}
void main(){
func(3, 20, 40, 30);
system("pause");
}*/
//c++中的类
myteacher.h
class myteacher{
public:
char* name;
int age;
public:
void setage(int age);
int getage();
void setname(char* name);
char* getname();
};
myteacher.c++
#include"myteacher.h"
void myteacher::setage(int age){
this->age = age;
}
int myteacher::getage(){
return this->age;
}
void myteacher::setname(char* name){
this->name = name;
}
char* myteacher::getname(){
return this->name;
}
/*#include"myteacher.h"
void main(){
myteacher t;
t.name = "jack";
t.age = 20;
cout << t.getname() << "," << t.getage() << endl;
system("pause");
}*/
/*
class teacher{
public:
char* name;
int age;
public:
//无参构造函数(写了,就会覆盖默认的无参构造函数)
teacher(){
cout << "无惨构造函数" << endl;
}
//有参构造函数会覆盖默认的构造函数
teacher(char* name, int age){
this->name = name;
this->age = age;
cout << name << "," </*
class teacher{
public:
char* name;
int age;
public:
//无参构造函数
teacher(){
this->name = (char*)malloc(sizeof(100));
strcpy(name, "jack");
age = 20;
cout << "无惨构造函数" << endl;
}
//析构函数
//当对象要被系统释放时,析构函数被调用
//作用:善后处理
~teacher(){
cout <<"析构函数"<< endl;
//这里会报错,
//free(this->name);
}
};
void func(){
teacher t;//会先调无惨构造函数,然后调析构函数
}
void main(){
func();
system("pause");
}*/
/*class teacher{
public:
char* name;
int age;
public:
//无参构造函数
teacher(){
this->name = (char*)malloc(sizeof(100));
strcpy(name, "jack");
age = 20;
cout << "无惨构造函数" << endl;
}
//拷贝构造函数(值拷贝)
//默认拷贝构造函数 就是值拷贝
teacher(const teacher & obj){
this->name = obj.name;
this->age = obj.age;
cout << "拷贝构造函数" << endl;
}
};
void fun(teacher t){
}
teacher fun2(teacher t){
return t;
}
void main(){
//不会调用拷贝构造函数
teacher t;
//如下情况才会调用拷贝构造函数
//1.声明时赋值
//teacher t1 = t;
//2.作为参数传入,实参给形参赋值
fun(t);//实际上执行了teacher t=t;
//3.作为函数返回值返回,给变量初始化赋值
teacher t2=fun2(t);//执行了三次 拷贝构造函数
system("pause");
}*/
/*浅拷贝问题:
由于浅拷贝后的对象和对象操作的是同一地址,
所以如果在析构函数中释放对象的话,不管是浅拷贝的对象还是对象释放完对象后如果再次释放就会报错。
class teacher{
private:
char *name;
int age;
public:
teacher(char *name, int age){
this->name = (char*)malloc(100);
strcpy(this->name, name);
this->age = age;
cout << "有参构造函数" << endl;
}
~teacher(){
cout << "析构" << endl;
//释放内存
free(this->name);
}
void myprint(){
cout << name << "," << age << endl;
}
};
void func(){
teacher t1("rose", 20);
//这里发生了浅拷贝
teacher t2 = t1;
t2.myprint();
}
void main(){
func();
system("pause");
}*/
//深拷贝
//深拷贝就是在拷贝时在内存中新开辟内存存放变量
class teacher{
private:
char *name;
int age;
public:
teacher(char *name, int age){
this->name = (char*)malloc(100);
strcpy(this->name, name);
this->age = age;
cout << "有参构造函数" << endl;
}
//深拷贝
teacher(const teacher& obj){
int len = strlen(obj.name);
this->name = (char*)malloc(len + 1);
strcpy(this->name, obj.name);
this->age = obj.age;
}
~teacher(){
cout << "析构" << endl;
//释放内存
free(this->name);
}
void myprint(){
cout << name << "," << age << endl;
}
};
void func(){
teacher t1("rose", 20);
//这里发生了浅拷贝
teacher t2 = t1;
t2.myprint();
}
void main(){
func();
system("pause");
}
推荐阅读
