C++面向对象的三大特征:封装、继承、多态
封装
1、概念:指将对象的属性和方法封装在一个独立的单元,对外部只提供必要的接口,隐藏内部的实现细节。这样,可以保护对象的数据及行为,避免外部的误操作及非法访问,提高了代码的安全性和可维护性。
2、访问权限:
- private:只允许本类的成员函数访问;
- public:可以被任意实体访问;
- protected:只允许子类和本类的成员函数访问;
继承
1、概念:让某个类型的对象获取另一个类型的对象属性的方法,即使子类具有父类的非私有属性和方法。这样,可以提升代码的可重用性、扩展性、可维护性。
多态
1、概念:向不同的对象发送相同的消息,不同的对象在接受时会产生不同的行为。在C++中有两种多态性,一种是静态的多态、一种是动态的多态;
2、两种多态:
-
静态多态:其实就是重载,是指在编译期就决定调用哪个函数,根据参数列表来决定;
函数的重载的规则:
1.函数名称必须相同。
2.参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)。
3.函数的返回类型可以相同也可以不相同。
4.仅仅返回类型不同不足以成为函数的重载。 -
动态多态:指通过子类重写父类的虚函数来实现,在运行期间决定调用哪个函数;
多态构成的条件:
1.必须通过基类的指针或者引用调用虚函数。
2.被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写。
为什么必须要是父类的指针或引用来调用虚函数,为什么不能是对象调用?
指针和引用调用、对象调用本质上是子类切片完成的,指针和引用的切片只针对子类中父类的那一部分,其他都不管,只管与父类一样的内容(虚表中)切片过去;如果是对象切片,就是将虚表里的内容全部切片过去(因为都是要调用构造函数的),那么就有可能父类也指向了子类的虚表,那就乱套了。可以理解为:指针和引用是将虚表的指针拷贝过去了,对象是将虚表中的内容拷贝过去了;
3、实现
//检测父类
class Base
{
public:
virtual void Detect() { cout << "运行父类检测" << endl; }
};
//检测毛刺类
class Burr: public Base
{
public:
virtual void Detect() { cout << "运行毛刺检测" << endl; }
};
//检测压伤类
class Dent: public Base
{
public:
void Detect() { cout << "运行压伤检测" << endl; }
};
//构成多态,传的哪个类型的对象,调用的就是这个类型的虚函数 --- 跟对象有关
void Func(Base& b) //或void Func(Base* b)
{
b.Detect(); //b->Detect();
}
int main()
{
Base b; //Base* b=new Base();
Func(b);
Burr burr; //Base* burr=new Burr();
Func(burr);
Dent dent; //Base* dent=new Dent();
Func(dent);
return 0;
}