C++练级之路——类和对象(上)

简介: C++练级之路——类和对象(上)

 

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修饰的成员在类外可以直接被访问;

2. protected和private修饰的成员在类外不能直接被访问 (此处protected和private的作用是类似的);

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;
};


和结构体差不多,类里面只计算成员变量的大小,而成员函数不占用类的空间,

所以一个类的大小,实际就是该类中“成员变量”之和,当然要注意内存对齐。

注意空类的大小,编译器给了空类一个字节来唯一标识这个类的对象(不同编译器对空类的处理可能不一样,这里用的编译器是vs2022)。

结构体内存对齐规则:


1. 第一个成员在与结构体偏移量为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。

VS中默认的对齐数为8

3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整

体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。


忘记的话可以复习前面的博客——浅谈结构体,

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指针的特性:


1. this指针的类型:类型* ,即成员函数中,不能给this指针赋值。

2. 只能在“成员函数”的内部使用

3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给 this形参。所以对象中不存储this指针。

4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传 递,不需要用户传递。



 

面试题:


1. this指针存在哪里?

栈区(形参一般存放在栈区)或者寄存器中。

 

2. this指针可以为空吗?

可以,但是不能对空指针解引用。

相关文章
|
15天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
25 2
|
21天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
54 5
|
27天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
56 4
|
28天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
66 4
|
2月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
28 4
|
2月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
23 1
|
2月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
25 4
|
2月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)
|
2月前
|
编译器 C++
【C++类和对象(中)】—— 我与C++的不解之缘(四)
【C++类和对象(中)】—— 我与C++的不解之缘(四)
|
2月前
|
存储 编译器 C语言
【C++类和对象(上)】—— 我与C++的不解之缘(三)
【C++类和对象(上)】—— 我与C++的不解之缘(三)