绪论
上一章,我们将c++入门的基础知识进行了学习,本章其实才算真正的跨入到c++开始可能比较难,但只有我们唯有不断的前进,才能斩断荆棘越过人生的坎坷!
话不多说安全带系好,发车啦(建议电脑观看)。
附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要
思维导图:
要XMind思维导图的话可以私信哈
目录
1.面向过程和面向对象的认识
2.类的引入
3.类的定义(class)
3.1类的访问限定符
4.封装
5.类的实例化
6.类对象模型
6.1计算类对象的大小
7.this指针
1.面向过程和面向对象的认识
面向过程、面向对象的概念:
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题;而C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。(过程就是完成一个事所要实现的步骤,而面向对象则是面向人,人们需要什么需求)
2.类的引入
知识点:
在c++中将struct升级成了类,此时不同于C语言,我们可以在结构体中定义函数
细节(具体):
- 如此时,在数据结构中实现功能的函数都是分开来写的,而在c++中因为struct升级成了类,类就可以把其中要实现的函数功能直接放在结构体中。
练习:
写一个类来实现栈的基本结构:
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<stdlib.h>
#include<assert.h>
using namespace std;
struct Stack
{
//成员函数
//在类域中不管声明的位置都能找得到
void Init(int DefaultCapacity = 4)
{
a = (int*)malloc(sizeof(int) * DefaultCapacity);
if (a == nullptr)
{
perror("malloc");
return;
}
capacity = DefaultCapacity;
size = 0;
}
void Push(int x)
{
if (size == capacity)
{
int* ptr = (int*)realloc(a, sizeof(int) * capacity * 2);
assert(ptr);
a = ptr;
capacity *= 2;
}
a[size++] = x;
}
int Top()
{
assert(size);
return a[size - 1];
}
// .... 就不过多的写了,此处了解语法即可
void Destroy()
{
free(a);
a = nullptr;
capacity = size = 0;
}
//成员变量
int* a;
int size;
int capacity;
};
int main()
{
Stack sk;
sk.Init(20);
sk.Push(1);
sk.Push(2);
sk.Push(3);
cout << sk.Top() << endl;//栈顶元素3
sk.Destroy();
return 0;
}
3.类的定义(class)
知识点:
- 基本语法和struct一样,只是换了个名称;class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略,类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数
- 语法:
class classname
{
//类体 ,有成员函数和成员变量组成
}; // 和结构体一样也要符号
3.1类的访问限定符
访问限定符:
publish(公有) 、 private (私有) 、 protect (保护)
1.public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. 如果后面没有访问限定符,作用域就到 } 即类结束。
5. class的默认访问权限为private,struct为public(因为struct要兼容C)
使用类定义时的细节:
- 成员函数的声明和定义全部放在类体时需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理,默认类里的成员函数是内联函数
- 类声明放在.h文件中,成员函数定义放在.cpp文件中时(分源管理):成员函数名前需要加类名::(因为在该函数中的name,sex,age 需要来源而来源就是类 , 来确定他是一个类里的成员函数的定义)
附:一般可以在成员变量的前/后/最前main加上m加上 _ , 来区分局部变量和成员变量
4.封装
知识点:
面向对象的三大特性:封装、继承、多态
封装定义:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互(本质封装是为了可以更好的管理)
封装的实例描述:
通过C语言和c++的角度来解释:
在c中我们结构体的成员变量不像c++中的成员变量一样可以进行私密(private),这样就会导致我们可以直接访问到结构体中的数据,而c++中对其进行了私密工作,我们无法在类外进行访问。
5.类的实例化
知识点:
用类类型创建对象(变量)的过程,称为类的实例化(当我们创建了一个类后,其中的成员变量其实并没有创建其只是一个声明,并没有实际的空间)。
所以说类的实例化就是把变量开辟一个空间,方法也很简单:就是用这个类创建一个变量即可。
实际举例如:
我们前面写的
此处就是一个实例化的例子,此后sk内的size capacity就实例化了 (也可以用实际的例子来解释:类就是一个图纸, 而我们用这个图纸来建造一个真正的房子这个房子就是这个类(图纸)的实例化 )
6.类对象模型
6.1计算类对象的大小
知识点:
在对象中只算成员变量的大小(和算结构体的方法一致同样也需要去内存对齐),成员函数是不算在其sizeof大小内的(因为成员函数其实并没有放到对象内而是放到了一个公共的区域,他就像一个小区里的篮球场并不需要每家都有,而是在一个公共的地方)
如果对结构体内存对齐有所忘记的同学可以去看一下这篇blog
细节:
- 对于类的大小,当是一个空类(没有成员变量的类对象)时是一个比较特殊的情况,此时编译器会给空类一个字节(为了占位表示其是存在的)
7.this指针
知识点:
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数(这个指针就是this),让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成(可以通过例子来更加深刻的认识this指针)
细节:
- this不能在形参或实参中显示使用,但是可以在函数内部显示使用
- this 指针的类型是:类 * const this
- this指针存在栈上(并不在对象中,因为其是一个形参就会存在函数调用的栈帧内)
- 在vs环境下,this指针会放到ecx寄存器中传参
通过实例来了解this指针:
//写一个日期类的类
class Date
{
public:
void Init(int year = 1970, int month = 1, int day = 1)
{
_day = day;
_month = month;
_year = year;
}
void Print()
{
cout << _year << ' ' << _month << ' ' << _day << endl;
}
private:
int _day;
int _month;
int _year;
};
int main()
{
Date d1;
Date d2;
d1.Init(2004, 9, 7);
d2.Init(2003, 7, 7);
d1.Print();
d2.Print();
return 0;
}
向上面这种情况为什么Print()函数中并没有传参数但是却能正确的找到对象,并且对对象中的数据进行打印呢、并且虽然前面有的d1. d2. 但这又能代表什么呢?
这其实就是隐含的this指针的作用,通俗来说就是当我们在前面确定了对象后,操作系统就会帮我们自动实现某种操作(其实也就是传对象的地址,并且有个this指针接收这个传进来的参数)
如:我们可以把 d1.Print ( );看成 d1 Print ( &d1 )
并且在函数内可以看成void Print(Date *const this)
{
cout <<this -> _year << ' ' <<this -> _month << ' ' <<this -> _day << endl;
}
其实和我们写数据结构中的一些结构很像,只是c++编译器中的类做了一些简化。
本章完。预知后事如何,暂听下回分解。
持续更新大量C++细致内容,希望对你有所帮助!早关注不迷路!