欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++的构造函数、析构函数、拷贝构造函数等代码实例讲解

程序员文章站 2022-03-23 19:37:14
c++的构造函数、析构函数、拷贝构造函数等代码实例讲解 #define _crt_secure_no_warnings #include #include #include #in...

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");
}
;>;>