一、类的内存空间
1、类本身是一种数据类型,在没有定义对象前是不占用内存空间的,定义对象的时候才会分配 空间
2、计算一个类的对象占用多少空间用sizeof(类名或对象)
1)类的内存空间大小是其数据成员(非静态-数据段)和虚表大小有关,跟函数成员无关
2)如果一个类中没有数据成员(空类),也没有虚表那么这个类的大小规定为1个字节
//类的实例化,也就是创建一个类的对象
GirlFriend mygirl1;
cout<<"size:"<<sizeof(GirlFriend)<<endl;
3、为什么空类的大小为1个字节
实际上,这是类结构体实例化的原因,空的类或结构体同样可以被实例化。如果定义对空的类或者结构体取sizeof()的值为0,那么该空的类或结构体实例化出很多实例时,在内存地址上就不能区分该类实例化出的实例。所以,为了实现每个实例在内存中都有一个独一无二的地址,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址,所以空类所占的内存大小是1个字节。通俗一点讲 就是 用空类实例化一个对象,这个对象的实体要存在内存中,既然要存在内存中那么就需要有个地址能访问他,为了避免多个实例对象的地址 问题,所以才有了者一个字节的空间。
二、构造函数
1、概念
函数名与类名相同,函数没有返回值, 函数不需要用户调用,在创建对象的时候自动调用。构造函数专注于在对象创建的初期的构造工作,具体来讲就是对对象各个成员的初始化。
2、格式
class 类名{
public:
类名(形参) //构造函数,一般放在public权限下
{
}
};
3、特点
- 构造函数的函数名和类型一致,并且没有返回值,而且定义的构造函数一般是放在public权限下
class GirlFriend{
public:
//类的构造函数,一般是放在public权限下
GirlFriend()
{
cout<<"GirlFriend()"<<endl;
}
}
- 定义对象的时候,编译器会自动调用对应的构造函数
GirlFriend mygirl;//自动调用了对应的构造函数 ---》 mygirl.GirlFriend();
GirlFriend mygirl();//自动调用了对应的构造函数 ---》 mygirl.GirlFriend(); ---这里有问题 编译可能会报错 ()要么不写,要么写参数进去
- 如果没有自定义构造函数,编译器就会自动生成默认(无参数、而且函数体是空的)的构造函数.
- 如果我们自定义了构造函数,那么编译器就不会帮助我们生成构造函数
- 自定义构造函数的函数体一般存放初始化信息
class GirlFriend{
public:
//类的构造函数,一般是放在public权限下
GirlFriend(int a)
{
cout<<"GirlFriend(int a)"<<endl;
}
}
int main()
{
//编译报错,因为我们自己定义了一个构造函数GirlFriend(int a),但是mygirl对象会调用没有参数的构造函数
//此时类中没有这种构造函数,所以会报错
//GirlFriend mygirl;
GirlFriend mygirl(10);//正确, 会自动调用 构造函数GirlFriend(int a)
}
三、构造函数的重载和默认参数
1、构造函数支持函数重载
class GirlFriend{
public:
//类的构造函数,必须放在public权限下
GirlFriend()
{
cout<<"GirlFriend()"<<endl;
}
GirlFriend(int a)
{
cout<<"GirlFriend(int a)"<<endl;
}
GirlFriend(int a,int b )
{
cout<<"GirlFriend(int a,int b )"<<endl;
}
}
创建对象的时候根据不同的参数调用不同的构造函数
GirlFriend mya;//调用构造函数 GirlFriend() ----不要写成GirlFriend mya();
GirlFriend myb(10);//调用构造函数 GirlFriend(int a)
GirlFriend myc(10,20);//调用构造函数 GirlFriend(int a,int b )
2、构造函数支持带默认参数
class GirlFriend{
public:
//类的构造函数
GirlFriend(int a=10,int b=20)
{
cout<<"GirlFriend(int a,int b )"<<endl;
}
}
如果在类外实现:
class GirlFriend