上一篇我们学习了C++的命名空间,这篇我们来了解一下C++的构造和析构函数
废话不多说,开始撸码
正文
构造函数、析构函数、拷贝构造函数
来个简单的例子,了解一下构造和析构的写法
class Teacher{
public:
int age;
public:
Teacher(){
cout << "无参构造函数" << endl;
}
~Teacher(){
cout << "析构函数" << endl;
}
};
当类没有构造函数的时候默认会有一个无参的构造函数,构造函数的作用是初始化变量,析构函数则释放资源
既然有了构造函数,那怎么创建对象呢?
无参构造: Teacher t;
有参构造: Teacher t1("lypop", 21);
Teacher t2 = Teacher("lypop", 21);
创建指针: Teacher *tt = new Teacher("lypop",21);
对于析构函数的调用,我们将创建放在一个方法里面,当方法执行结束便会执行析构函数
class Teacher{
private:
char *name;
int age;
public:
Teacher(){
this->name = (char*)malloc(100);
strcpy(name, "lypop");
age = 20;
cout << "无参构造函数" << endl;
}
//析构函数
~Teacher(){
cout << "析构" << endl;
//释放内存
free(this->name);
}
};
void func2(){
Teacher t;
}
我们只需要在析构函数中释放相应的资源
除了构造函数和析构函数,类里面有个默认的拷贝构造函数,它只是一种值拷贝,当类中有指针属性的时候容易发生崩溃。所以当我们类中有指针需要在析构函数释放资源的时候,拷贝构造函数都使用深拷贝
下面来看一下值拷贝(浅拷贝)
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 func(){
Teacher t1("rose", 20);
Teacher t2 = t1;//这时候会调用默认的拷贝构造函数
}
当func执行完毕之后就会调用两次析构,因为只是简单的值拷贝,name指针指向的是同一块内存地址,当第一个被释放掉在释放第二个的时候就会出错。所以需要解决这种就需要深拷贝,也就是重写拷贝构造函数为name重新开辟一块内存地址
//深拷贝
Teacher(const Teacher &obj){
//复制name属性
int len = strlen(obj.name);
this->name = (char*)malloc(len+1);
strcpy(this->name,obj.name);
this->age = obj.age;
}
拷贝构造函数被调用的场景:
- 声明时赋值
- 作为参数传入,实参给形参赋值
- 作为函数返回值返回,给变量初始化赋值
C和C++创建指针和释放资源
C 创建 int *p1 = (int*)malloc(sizeof(int) * 10);
释放 free(p1);
C++创建 int *p2 = new int[10];
释放 delete[] p2;//释放数组指针 delete p;//释放指针
C++访问静态属性和方法
通过类名::来访问,也可以通过类对象来访问
int Teacher::total = 9;
Teacher::total++;
Teacher::count();
常量对象、常函数
Teacher *const this;能改变指针指向的内容,不能改变指针的值
const Teacher* const this;既不能改变指针的值,又不能改变指针指向的内容
常量对象只能调用常量函数,不能调用非常量函数。常函数当前对象不能被修改,防止数据成员被非法访问
class Teacher{
void myprint() const{
}
};
void main(){
const Teacher t1("aaa",22);
t.myprint();
system("pause");
}
友元函数、友元类
友元函数的实现,在友元函数中可以访问私有的属性
class A{
friend void modify_i(A *p, int a);
private:
int i;
};
void modify_i(A *p, int a){
p->i = a;
}
友元类中可以访问友元对象所在类的所有成员
class A{
friend class B;
private:
int i;
};
class B{
public:
//B这个友元类可以访问A类的任何成员
void accessAny(){
a.i = 30;
}
private:
A a;
};
运算符重载
-
类外进行运算符重载
class Point{ public: int x; int y; public: Point(int x = 0, int y = 0){ this->x = x; this->y = y; } void myprint(){ cout << x << "," << y << endl; } }; Point operator+(Point &p1, Point &p2){ Point tmp(p1.x+p2.x,p1.y+p2.y); return tmp; } Point operator-(Point &p1, Point &p2){ Point tmp(p1.x - p2.x, p1.y - p2.y); return tmp; }
-
类内进行运算符重载
class Point{ public: int x; int y; public: Point(int x = 0, int y = 0){ this->x = x; this->y = y; } //成员函数,运算符重载 Point operator+(Point &p2){ Point tmp(this->x + p2.x, this->y + p2.y); return tmp; } void myprint(){ cout << x << "," << y << endl; } };
-
当属性私有的时候需要使用友元函数实现运算符重载
class Point{ friend Point operator+(Point &p1, Point &p2); private: int x; int y; public: Point(int x = 0, int y = 0){ this->x = x; this->y = y; } void myprint(){ cout << x << "," << y << endl; } }; Point operator+(Point &p1, Point &p2){ Point tmp(p1.x + p2.x, p1.y + p2.y); return tmp; }
但是运算符重载的本质还是函数的调用,至此C++的类就总结到这里,谢谢不耐其烦的看完。
网友评论