目录
1.类的概念
2.对象的概念
3.构造函数
4.析构函数
5.拷贝构造函数
众所周知,C++是一门面对对象的语言,而面对对象的语言具有三大特性(封装 继承 多态)
C++中的对象与C语言中的结构体具有极大的相似性(可以理解成对象是结构体的升级版)
上面是一个简单的类的定义
1. 类定义后会加一个 ; 这个与结构体一致
2.一个类可以定义多个对象,每一个对象都是一个变量
3.类和结构体一样,都是自定义类型,计算内存时,要考虑内存对齐
4.类里面可以有 变量 和 函数
5.类的访问 依然用 . 或 -> 访问
类的定义 可以分为两种方式 struct定义 class定义
区别:
struct 定义的变量和函数均是 public(公共属性)
class 分为 public private protected
举个例子:
struct 默然是公共属性 class默然是私有属性
对象的概念:
对象就是类的实例化
注意:类里面是可以嵌套的
注意:private 后面接的是变量的声明,而不是定义 B s是变量的定义
下面讲解构造函数
1.函数名与类名相同
2.无返回值
3.对象实例化时,编译器自动调用对应的构造函数(这一点特别重要)
4.构造函数可以重载(要注意是否会产生调用歧义)
举个例子:
第一点:当我们没有写构造函数,编译器会自动生成一个构造函数,这个构造函数对内置类型(包括int double char float 指针等)不处理,对自定义类型(结构体和类)调用他自己的构造函数
此时你会发现内置类型再去调用它的构造函数,最终还是对内置类型进行初始化
第二点:当我们在定义对象时,没有传参,此时他会调用它的默认构造函数
补充:默认构造函数有三种 无参构造 全缺省构造 编译器默认生成的构造函数(当我们写了构造函数,编译器不会生成了)
举个例子:
A s 代表无参构造 ,则调用默认构造函数,此时由于已经有A(.....) 编译器不会自动生成 , 则没有默认构造函数
还有一种初始化的方法
#include <iostream>
using namespace std;
class A
{
public:
private:
int _a = 1;
int _b = 2;
int _c = 3;
};
int main()
{
A s;
return 0;
}
这段带码的含义是由于没有写构造函数,编译器自动生成,但此时由于我写了int _a = 1.......
相当于这个代码 这两个代码等效
析构函数:(相当于destory, 销毁对象的空间)
析构函数主要是对从堆上拿来的空间释放,防止内存泄漏
格式:~ + 类型名(注意析构函数没有返回值)
注意析构函数不能函数重载,一个类只能有一个析构函数
当对象里面有自定义类型时,回去调用它的析构函数,对于内置类型,就调用自己的析构函数,如果没有,就不做处理
#include <iostream>
using namespace std;
class B
{
public:
~B()
{
cout << 1 << endl;
}
};
class A
{
public:
A( int a = 1 , int b = 2 , int c = 3 )
{
_arr = (int*)malloc(sizeof(int)*10);
_a = a;
_b = b;
_c = c;
}
~A()
{
free(_arr);
_a = 0;
_b = 0;
_c = 0;
}
private:
class B t;
int* _arr;
int _a ;
int _b ;
int _c ;
};
int main()
{
A s;
return 0;
}
下面的代码就会打印出来1
拷贝构造函数:
用一个现有的对象去初始化未知的对象
#include <iostream>
using namespace std;
class A
{
public:
A()
{
_a = 1;
_b = 2;
}
A(const A& t)拷贝构造函数用的是&引用
{
this->_a = t._a;
this->_b = t._b;
}
private:
int _a;
int _b;
};
int main()
{
A s;
A t(s);
return 0;
}
如果我们没写拷贝构造函数,那么编译器会自动生成一个拷贝构造函数,请注意这一拷贝构造函数是浅拷贝(就是通过字节上面存储的数值,一个一个字节的拷贝)
这时会出现一个Bug
#include <iostream>
using namespace std;
class A
{
public:
A()
{
_arr = (int*)malloc(sizeof(int)*100);
_a = 1;
_b = 2;
}
~A()
{
free(this->_arr);
}
private:
int* _arr;
int _a;
int _b;
};
int main()
{
A s;
A t(s);
return 0;
}
这个代码会崩溃
原因:
s的指针与t的指针指向同一块区域
当free时,程序崩溃
此时,要进行深拷贝
#include <iostream>
using namespace std;
class A
{
public:
A()
{
_arr = (int*)malloc(sizeof(int)*100);
_a = 1;
_b = 2;
}
A( const A& t )
{
int* temp = (int*)malloc(sizeof(int)*10);
if( !temp )
exit(1);
this->_arr = temp;
this->_a = t._a;
this->_b = t._b;
}
~A()
{
free(this->_arr);
}
private:
int* _arr;
int _a;
int _b;
};
int main()
{
A s;
A t(s);
return 0;
}
结论:当要malloc空间时,要进行深拷贝