面向过程:是一种以过程为中心的编程思想。都是以什么正在发生为主要目标进行编程。C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。 面向对象:是一类以对象作为基本程序结构单位的程序设计语言,指用于描述的设计是以对象为核心,而对象是程序运行时刻的基本成分。C++语言是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。


在C语言中,结构体中只能定义变量,但在C++中,结构体内不仅可以定义变量,还可以定义函数。
struct Test
{
//成员变量
int a;
double b;
//成员函数
int Add(int x, int y)
{
return x + y;
}
};但上面结构体的定义,在C++中更喜欢用class来代替。
class className
{
//类体:由成员变量和成员函数组成
}; //注意后面的分号
2、声明放在头文件(.h)中,定义放在源文件(.cpp)中

注意: 一般情况下,更期望采用第二种方式。

【访问限定符说明】 1、public修饰的成员可以在类外直接被访问,在类中可以直接访问。 2、protected和private修饰的成员在类外不能直接被访问。 3、访问权限从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。 4、class的默认访问权限为private,struct为public(因为struct要兼容C)。 注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别 面试题: C++中的struct和class的区别是什么? C++需要兼容C语言,所以C++中的struct可以当成结构体去使用。此外,C++中的struct还可以用来定义类,和class定义类是一样的,区别是struct的成员默认访问权限是public,而class的成员默认访问权限是private。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
封装本质上是一种管理:想想我们是如何管理陕西省的兵马俑的。我们若什么都不管,兵马俑就被随意破坏了。所以我们建立了一座房子将兵马俑封装起来。但是我们封装的目的不是为了不给别人看,所以我们开放了售票通道,人们可以通过买票突破封装,在合理的监管机制下进去参观。

类也是一样,我们使用类将数据和方法都封装起来。不想对外开放的就用 protected/private 封装起来,用 public 封装的成员允许外界对其进行合理的访问。所以封装本质上是一种管理。
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用“::”作用域解析符指明成员属于哪个类域。
class Person
{
public:
//显示基本信息
void ShowInfo();
private:
char* _name; //姓名
char* _sex; //性别
int _age; //年龄
};
//这里需要指定ShowInfo是属于Person这个类域
void Person::ShowInfo()
{
cout << _name << "-" << _sex << "-" << _age << endl;
}#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
typedef int STDateType;
class Stack
{
public:
void StackInit(int initSize = 4);
void StackPush(STDateType x);
private:
STDateType* a;
int size;
int capacity;
};
class A1
{
};
class A2
{
void fun()
{
}
};
int main()
{
Stack st; //类的实例化,创建一个对象st
cout << sizeof(st) << std::endl;
cout << sizeof(A1) << std::endl;
cout << sizeof(A2) << std::endl;
return 0;
}一个类当中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?类的大小又是如何计算的呢?
class Person
{
public:
//显示基本信息
void ShowInfo()
{
cout << _name << "-" << _sex << "-" << _age << endl;
}
public:
char* _name; //姓名
char* _sex; //性别
int _age; //年龄
};


对于上述两种存储方式,计算机是按照哪种方式来存储的,我们可以通过对下面的不同对象分别获取大小来进行分析:

结论: 一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类。
对齐数 = 该结构体成员变量自身的大小与编译器默认的一个对齐数的较小值。
面试题
结构体怎么对齐? 为什么要进行内存对齐? 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据,某些硬 件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常 硬件原因:经过内存对齐之后,CPU的内存访问速度大大提升。
如何让结构体按照指定的对齐参数进行对齐? #pragma pack(n)//强制使对齐模数为n(不管VS和Linux)
什么是大小端?如何测试某台机器是大端还是小端,有没有遇到过要考虑大小端的场景? 大端存储模式:就是内存的低地址上存着数据的高位,高地址上存着数据的低位。 小端存储模式:就是内存的低地址上存数据的低位,而高地址上存数据的高位。 大小端场景:代码移植和网络通信。 结构体内存对齐详解——》请点击
我们先来定义一个日期类的Date:
#include <iostream>
using namespace std;
class Date
{
public:
void Display()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
void SetDate(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year; // 年
int _month; // 月
int _day; // 日
};
int main()
{
Date d1, d2;//实例化两个日期类
d1.SetDate(2021, 5, 25);//设置d1的日期
d2.SetDate(2021, 5, 26);//设置d2的日期
d1.Display();//打印d1的日期
d2.Display();//打印d2的日期
return 0;
}上述Date类中有SetDate和Display两个成员函数,函数体中并没有关于不同对象的区分,那么当d1调用SetDate函数时,该函数是如何知道要设置的是d1对象,而不是d2对象呢?
C++中通过引入this指针解决该问题:C++编译器给每个“非静态的成员函数”增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问的。只不过所有操作对用户是透明的,即用户不需要来传递,而是编译器自动完成。
上述代码调用成员函数传参时,看似只传入了一些基本数据,实际上还传入了指向该对象的指针:

编译器进行编译时,看到的成员函数实际上也和我们所看到的不一样,每个成员函数的第一个形参实际上是一个隐含的this指针,该指针用于接收调用函数的对象的地址,用this指针就可以很好地访问到该对象中的成员变量:

#include <iostream>
using namespace std;
class A
{
public:
void PrintA()
{
cout << _a << endl;
}
void Show()
{
cout << "Show()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
//p->Show(); //第一句代码
//p->PrintA(); //第二句代码
}程序分别运行第一句代码和第二句代码,你认为程序运行的结果如何? 你可能看到指针p是一个空指针,而第二句代码和第三句代码都通过操作符“->”,间接性的执行了对p的解引用操作,所以你认为程序会崩溃。 其实不然,当程序执行第一句代码时,程序不会崩溃,会正常打印出字符串"Show()",而当程序执行第二句代码时,程序才会因为内存的非法访问而崩溃。
解释如下: 指针p确实是一个类的空指针,但当执行第一句代码时,程序并不会崩溃。第一句代码并没有对空指针p进行解引用,因为Show等成员函数地址并没有存到对象里面,成员函数的地址是存在公共代码段的。 当程序执行第二句代码时,会因为内存的非法访问而崩溃。执行第二句代码时,调用了成员函数PrintA,这里并不会产生什么错误(理由同上),但是PrintA函数中打印了成员变量_a,成员变量_a只有通过对this指针进行解引用才能访问到,而this指针此时接收的是nullptr,对空进行解引用必然会导致程序的崩溃。