1、类的定义
class 类名{
//成员函数
//成员变量
};
class为定义的关键字,{ }内是类的主体,注意后面的 ; 不要忘了
类体中的内容成为类的成员,类中的变量为成员变量或类的属性,类中的函数为成员函数或类的方法,
类的两种定义方式:
1、声明和定义都放在类中, 需注意成员函数如果在类中定义,编译器可能会将其当成内联函数处理;
2、声明和定义分离,在头文件中声明,在源文件中定义,
一般情况下,都采用第二种方式;
2、成员变量的命名方式
成员变量和函数形参的名字注意区别,比如下面的代码:
class Date
{
public:
void Init(int year)
{
// 这里的year到底是成员变量,还是函数形参?
year = year;
}
private:
int year;
};
为了方便区分我们通常会做一些区别,让他们看起来有联系,又容易区分:
class Date
{
public:
void Init(int year)
{
_year = year;
}
private:
int _year;
};
3、类的访问限定符
C++实现封装的方式:用类将对象的属性和方法绑定到一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
访问限定符说明:
1.public修饰的成员在类外可以直接被访问;
- protected和private修饰的成员在类外不能直接被访问 (此处protectedhepriyate的作用是类似的);
3.访问权限的作用域从该访问限定符出现的位置开始,直到下一个访问限定符出现时为止;
4.如果后面没有访问限定符,作用域就到 } 即类结束为止;
5.class默认访问权限是private,struct默认是public(因为要兼容C)。
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。
问题:C++中class和struct的区别是什么?
C++中struct可以当作结构体来用,因为要兼容C,也可以定义类,和class定义类差不多,区别是struct定义的类默认是public,而class定义的类默认是private。注意:在继承和模板参数列表位置,struct和class也有区别,后序给大家介绍。
4、封装
面对对象的三大特性:封装,继承,多态。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
在C++语言中实现封装,可以通过类将数据和操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以直接在类外部被使用访问。
5、类对象模型
如何计算类的大小?
class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
private:
char _a;
};
和结构体差不多,类里面只计算成员变量的大小,而成员函数不占用类的空间,
所以一个类的大小,实际就是该类中"成员变量"之和,当然要注意内存对齐。
注意空类的大小,编译器给了空类一个字节来唯一标识这个类的对象。
结构体内存对齐规则:
- 第一个成员在与结构体偏移量为 0 的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS 中默认的对齐数为 8- 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
忘记的话可以复习前面的博客------浅谈结构体,
6、this指针
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout <<_year<< "-" <<_month << "-"<< _day <<endl;
}
private:
int _year; // 年
int _month; // 月
int _day; // 日
};
int main()
{
Date d1, d2;
d1.Init(2022,1,11);
d2.Init(2022, 1, 12);
d1.Print();
d2.Print();
return 0;
}
Date类中有Init与Print两个成员函数,函数体中没有关于不同对象的区分,那当d1调用Init函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?
C++中通过引入 this 指针解决该问题,即: C++ 编译器给每个 " 非静态的成员函数 "增加了一个隐藏
的指针参数,让该指针指向当前对象( 函数运行时调用该函数的对象 ) ,在函数体中所有 " 成员变量"
的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编
译器自动完成。
this指针的特性:
- this 指针的类型:类型 * const ,即成员函数中,不能给 this指针赋值。
- 只能在 " 成员函数"的内部使用
- this 指针本质上是 " 成员函数 " 的形参,当对象调用成员函数时,将对象地址作为实参传递给
this形参。所以 对象中不存储 this 指针。 - this 指针是 " 成员函数 " 第一个隐含的指针形参,一般情况由编译器通过 ecx寄存器自动传
递,不需要用户传递。
面试题:
- this 指针存在哪里?
栈区(形参一般存放在栈区)或者寄存器中。 - this 指针可以为空吗?
可以,但是不能对空指针解引用。