类是一种特殊的自定义类型,自定义类型遵守C语言中所有数据类型的操作,也可以用来定义指针,这种特殊的自定义类可以用来定义变量,从面向对象的角度就是实例化一个对象了,从程序的本质上来将就是定义一个自定义类型的变量,既然是变量它就需要占用存储空间,占用什么区域的存储空间和C语言中的说法一致,即局部变量在栈空间,全局变量在静态存储区(.bss 和 .data段)
例子:
#include <stdio.h>
class Test
{
private:
int i;
int j;
public:
int getI() { return i; }
int getJ() { return j; }
};
Test gt;
int main()
{
printf("gt.i = %d\n", gt.getI());
printf("gt.j = %d\n", gt.getJ());
Test t1;
printf("t1.i = %d\n", t1.getI());
printf("t1.j = %d\n", t1.getJ());
Test* pt = new Test;
printf("pt->i = %d\n", pt->getI());
printf("pt->j = %d\n", pt->getJ());
delete pt;
return 0;
}
编译结果:
sice@sice:~/DT$ g++ a.cpp
sice@sice:~/DT$ ./a.out
gt.i = 0
gt.j = 0
t1.i = 0
t1.j = 134514073
pt->i = 0
pt->j = 0
可以知道t1就是局部变量,它占用的空间在栈上面,既然它在栈上面占用了存储空间,它的成员变量又没有初始值,自然它们的初始值就不确定了,gt对象在是个全局变量初始化为0,new跟C语言中的malloc大同小异,本质上也是向堆空间申请内存,pt指向堆空间里面申请的Test类型的对象,在我们之前学习中在堆空间得到的变量的初始值是不定的,这里为0只是g++编译器在linux平台下的优化,delete相当于free,用于堆空间的释放
一般而言,对象都需要一个确定的初始化状态(类似手机类里面的iphone4s对象有出厂设置的初始状态一样),我们怎么使得无论在哪里创建对象,对象的成员的初始值都为0呢?
解决方案
在类中提供一个public的initialize函数
对象创建后立即调用initialize函数进行初始化
#include <stdio.h>
class Test
{
private:
int i;
int j;
public:
int getI() { return i; }
int getJ() { return j; }
void initialize()
{
i = 1;
j = 2;
}
};
Test gt;
int main()
{
gt.initialize();
printf("gt.i = %d\n", gt.getI());
printf("gt.j = %d\n", gt.getJ());
Test t1;
//t1.initialize();
/*错误的示范*/
printf("t1.i = %d\n", t1.getI());
printf("t1.j = %d\n", t1.getJ());
t1.initialize();
Test* pt = new Test;
pt->initialize();
printf("pt->i = %d\n", pt->getI());
printf("pt->j = %d\n", pt->getJ());
delete pt;
return 0;
}
优化方案
我们的initialize函数必须在对象创建后就调用,那就存在人工的疏忽,我们需要将它自动化,所以C++里面提供了构造函数,构造函数的函数名与类名相同,构造没有任何返回类型的声明,构造函数在对象定义时自动被调用
代码:
#include <stdio.h>
class Test
{
private:
int i;
int j;
public:
int getI(void){return i;}
int getJ(void){return j;}
Test()
{
printf("Test() Begin\n");
i = 2;
j = 1;
printf("Test() End\n");
}
};
Test a;
int main(void)
{
printf("a.i = %d\n", a.getI());
printf("a.j = %d\n", a.getJ());
Test b;
printf("b.i = %d\n", b.getI());
printf("b.j = %d\n",b.getJ());
Test* c = new Test;
printf("c->i = %d\n", c->getI());
printf("c->j = %d\n", c->getJ());
delete c;
return 0;
}
结果:
sice@sice:~/DT$ ./a.out
Test() Begin
Test() End
a.i = 2
a.j = 1
Test() Begin
Test() End
b.i = 2
b.j = 1
Test() Begin
Test() End
c->i = 2
c->j = 1