一、构造器
1、构造器的定义和意义
- 有函数的特性,但又不是函数
class 类名
{
类名(形式参数)
构造体
}
class A
{
A(形参)
{
2、规则
- 在类对象创建时,自动调用,完成类对象的初始化。尤其是动态堆内存的申请
- 与类同名,无返回值
- 系统默认有无参空构造器
- 一经自定义,则系统默认不再提供。(定义了自己的构造器,默认的就不存在了)
- 可以被重载与默认参数
例:
using namespace std;
class Stack
{
public:
Stack();
Stack(int size=1024); //重载,构造器可以有默认参数
~Stack(); //析构器(这个程序的stack s属于在栈上的,只有main函数退出时,才调用析构器)
void init();
bool isEmpty();
bool isFull();
void push(int data);
int pop();
private:
int* space;
int top;
};
Stack::Stack(int size) //构造器
{
space = new int[size];
top = 0;
}
Stack::~Stack()
{
delete []space;
}
bool Stack::isEmpty()
{
return top == 0;
}
bool Stack::isFull()
{
return top == 1024;
}
void Stack::push(int data)
{
space[top++] = data;
}
int Stack::pop()
{
return space[--top];
}
int main()
{
// Stack s; //会有默认的无参构造器
Stack s(100); //这个里面写值,构造器就必须有参数(这个没有默认的构造器)
if(!s.isFull())
s.push(10);
while(!s.isEmpty())
cout<<s.pop()<<endl;
return 0;
}
3、参数初始化表
- 完成初始化效率高,b格高
data::data(int y,int m,int d)
:year(y),month(m),day(d) //在函数还没有调用及执行下面的作用域之前就完成了初始化, 一定要注意是一个点,不是两个点
}
- 初始化列表中的初始化顺序, 与声明顺序有关, 与前后赋值顺序无关
- 尽量使用参数列表,程序的效率提高,减少一次压栈出栈,没有创建对象之前就先初始化完成了
using namespace std;
class A
{
public:
A(char * ps)
:name(ps),len(strlen(name.c_str())){}
/*
A(char * ps)
:name(ps)
{
len=strlen(name.c_str());
}
*/ //这种 情况下输出的也是正确的5
void dis()
{
cout<<len<<endl;
}
private:
int len;
string name; //先声明len再声明name输出的结果是随机的一个野指针的值,但是先声明name再声明len输出的结果是china的长度5
};
int main()
{
A a("china");
a.dis();
return 0;
}
二、析造器(Destructor)
1、析构体的定义和规则
- 无返值 ,与类名同。无参。不可以重载与默认参数
- 对象销毁时,自动调用。完成销毁的善后工作
- 栈对象离开其作用域,堆对象被手动 delete
class 类名
{
~类名()
析造体
}
class A
{
~A()
{}
}
例:
主函数中:data s(2017,2,1);
data::data(int y,int m,int d) //这种的可以不做析构
{
year = y;
mouth = m;
day = d;
}
data::~data() //有数组或者内存申请时就需要析构了
{
delete []space;
}
2、何时调用,对象销毁时期
- 栈对象离开其作用域
- 堆对象被手动 delete
例:由调用delete析构函数调用5次,没有则输出三次
using namespace std;
class stack{
public:
stack (int size = 100){ //加上默认参数之后,stack s;和stack s(102);两个都可以使用了
top =0;
space =new int[size];
memset(space,0,size);
}
~stack(){
delete []space;
cout<<"stop"<<endl;//有下面的delete这句话输出5次,没有则输出三次
}
private:
int top;
int *space;
};
int main ()
{
stack s;
stack ss(200);
{
stack sss;
} //这个是属于在栈中,栈对象离开其作用域之后,立刻调用~stack函数
{
stack * h = new stack[5];
delete []h; //如果没有这句话,则不会执行~stack,所以堆对象需要手动delete
}
return 0;
}
3、小结
- 析构函数的作用,并不是删除对象,而在对象销毁前完成的一些清理工作
- 类中的函数是不占用内存空间的,只有变量才占用内存空间
例:
class data
{
public :
void haha();
void enen();
private:
int year;
int month;
}
int main (0
{
data s;
cout<<sizeof(data)<<sizeof(s)<,endl; //输出的结果都是8
}
三、多文件编程
- 通常我们将类的声明放到头文件中,将类的定义放到.cpp文件中