1、面向过程和面向对象的区别
1.1 面向过程
面向过程是一种自上而下的程序设计方法。过程式的特征是以函数为中心,用函数作为划分程序的基本单位。
关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
优点:
- 性能比面向对象高。因为类调用时需要实例化,开销比较大,比较消耗资源。
缺点:
- 没有面向对象易维护、易复用、易扩展
1.2 面向对象
面向对象是一种自下而上的程序设计方法。以数据为中心,类是表现数据的单位,是划分程序的基本单位。
关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
优点:
- 易维护、易复用、易扩展。由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护。
缺点:
- 性能比面向过程低
2、封装
面向对象的三大特性:封装、继承、多态。
将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
定义了一个类,相当于定义了一个新的作用域。
3、类的实例化
用类类型创建对象的过程,称为类的实例化。
一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。
类中只保存成员变量,成员函数存放在公共的代码段。
3.1 空类的大小为什么是一个字节?
C++ 标准指出,不允许一个对象的大小为0,不同的对象不能具有相同的地址:
① 由于new需要分配不同的内存地址,不能分配内存大小为0的空间
② sizeof(T)避免出现0的错误
注意:
- 在继承体系下,如果子类中有数据成员,那么父类中的一个字节不会加到子类中
- 空类中含有 this 指针,该指针为null,没有用到没问题,用到则会导致程序崩溃。
4、this指针
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,即“this指针”,让 this 指针指向当前对象。在函数体中所有成员变量的操作,都是通过this指针去访问。
4.1 this指针的特性
- this指针类型:类类型* const
- 作用范围:只能在“成员函数”的内部使用
- this指针本质:this指针是成员函数第一个隐含的指针形参。在对象调用成员函数时,将对象地址作为实参传递给this形参。
- this指针传递:一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。
5、类六大默认函数
https://blog.csdn.net/weixin_43967449/article/details/109012850
6、再谈构造函数
初始化列表:以一个冒号开始,接着是以逗号分隔的数据成员列表,每个成员变量后跟一个放在括号中的初始值或表达式
class Date{
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
6.1 注意
- 每个成员变量在初始化列表只能初始化一次,构造函数内可以进行多次赋值
- 引用成员变量、const成员变量、自定义类型成员(该类没有默认构造函数)必须放在初始化列表位置进行初始化
- 成员变量在类中声明次序就是在初始化列表中的初始化顺序
6.2 explicit关键字
C++中的explicit关键字只能用于修饰只有一个参数的类构造函数,它的作用是表明该构造函数是显示的。另一个关键字是implicit,类构造函数默认情况下,声明为隐式的。
用explicit修饰构造函数,将会禁止单参构造函数的隐式转换。
7、static成员
7.1 概念
声明为static的类成员称为类的静态成员。用static修饰的成员变量,称为静态成员变量,用static修饰的成员函数,称为静态成员函数。静态成员变量一定要在类外初始化。
7.2 特性
- 静态成员只有一份,所有类对象共享。
- 静态成员变量必须在类外定义,定义时不添加static关键字
- 静态类成员访问:类名: : 静态成员(Date: :GetDate() )、对象.静态成员(d.GetDate())
- 静态成员函数没有this指针,不能访问任何非静态成员
- 静态成员也有public,protected,private3种访问级别,也可以具有返回值
7.1 面试题中常见的C++常用关键字
8、C++11的成员就地初始化
非静态成员变量,可以在类声明中进行就地列表初始化(=或{}都可以),但初始化列表的效果优于就地初始化。
class B
{
public:
B(int b = 0)
: _b(b)
{}
int _b;
};
class A
{
public:
void Print()
{
cout << a << endl;
cout << b._b << endl;
cout << p << endl;
}
private:
// 非静态成员变量,可以在成员声明时就地初始化
int a = 10;
B b = 20;
int *p = (int*)malloc(4);
static int n;
};
9、友元
友元提供了一种突破封装的方式。
9.1 友元函数
友元函数可以直接访问类的私有成员,它定义在类的外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字
class Date
{
friend ostream& operator<<(ostream& _cout, const Date& d);
friend istream& operator>>(istream& _cin, Date& d);
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
_cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
istream& operator>>(istream& _cin, Date& d)
{
_cin >> d._year;
_cin >> d._month;
_cin >> d._day;
return _cin;
}
int main()
{
Date d;
cin >> d;
cout << d << endl;
return 0;
}
9.2 友元函数特性
- 友元函数可访问类的私有和保护成员,但不是类的成员函数
- 友元函数不能用const修饰
- 友元函数可以在类定义的任何地方声明,不受类访问限定符限定
- 一个函数可以是多个类的友元函数
- 友元函数的调用与普通函数调用原理相同
9.3 友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
- 友元关系是单向的,不具有交换性
- 友元关系不能传递
10、内部类
10.1 概念
如果一个类定义在另一个类的内部,这个内部类就叫做内部类。
- 内部类就是外部类的友元类。
- 特性:内部类可以定义在外部类的public,protected,private
- 注意内部类可以直接访问类中的static,枚举成员,不需要外部类的对象/类名
- sizeof(外部类) == 外部类,和内部类没有任何关系
class A
{
private:
static int k;
int h;
public:
class B
{
public:
void foo(const A& a)
{
cout << k << endl;
cout << a.h << endl;
}
};
};
int A::k = 1;
int main()
{
A::B b;
b.foo(A());
return 0;
}