✍个人博客:Pandaconda-CSDN博客
📣专栏地址:http://t.csdnimg.cn/fYaBd
📚专栏简介:在这个专栏中,我将会分享 C++ 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
1. 介绍面向对象的三大特性,并且举例说明
三大特性:继承、封装和多态
(1)继承
让某种类型对象获得另一个类型对象的属性和方法。
它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
常见的继承有三种方式:
-
实现继承:指使用基类的属性和方法而无需额外编码的能力
-
接口继承:指仅使用属性和方法的名称、但是子类必须提供实现的能力
-
可视继承:指子窗体(类)使用基窗体(类)的外观和实现代码的能力(C++里好像不怎么用)
例如,将人定义为一个抽象类,拥有姓名、性别、年龄等公共属性,吃饭、睡觉、走路等公共方法,在定义一个具体的人时,就可以继承这个抽象类,既保留了公共属性和方法,也可以在此基础上扩展跳舞、唱歌等特有方法。
继承的好处:
-
代码的复用。
-
通过继承,在基类里面给所有派生类可以保留统一的纯虚函数接口,等待派生类进行重写,通过使用多态,可以通过基类的指针访问不同派生类对象的同名覆盖方法。
(2)封装
数据和代码捆绑在一起,避免外界干扰和不确定性访问。
封装是指将数据(属性)和操作数据的方法(函数)封装在一个单元中,这个单元就是类。封装的主要目的是隐藏类的内部实现细节,只暴露必要的接口给外部使用者。
优点:
-
信息隐藏:封装可以将类的内部细节隐藏起来,不暴露给外部,提高了安全性和防止误用。
-
简化接口:封装通过提供清晰的接口简化了类的使用,使用者只需关注如何使用接口而不需要了解内部实现。
-
提高可维护性:内部实现的修改不会影响外部使用者,从而提高了代码的可维护性。
(3)多态
同一事物表现出不同事物的能力,即向不同对象发送同一消息,不同的对象在接收时会产生不同的行为(重载实现编译时多态,虚函数实现运行时多态)。
多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单一句话:允许将子类类型的指针赋值给父类类型的指针
实现多态有二种方式:覆盖(override),重载(overload)。
-
覆盖:是指子类重新定义父类的虚函数的做法。
-
重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。例如:基类是一个抽象对象——人,那教师、运动员也是人,而使用这个抽象对象既可以表示教师、也可以表示运动员。
另外,还有多态的几个关键概念和特性:
-
虚函数(Virtual Functions):通过将函数声明为虚函数,可以实现动态绑定。虚函数是在基类中声明,并在派生类中重新定义的函数。在运行时,根据对象的实际类型确定调用哪个函数的过程就是动态绑定。
-
纯虚函数(Pure Virtual Functions):纯虚函数是一种在基类中声明但没有具体实现的虚函数。它的目的是为了在基类中提供一个接口,要求派生类必须实现这个函数,从而使基类成为抽象类。抽象类不能被实例化,只能用作派生类的基类。
-
虚析构函数(Virtual Destructors):虚析构函数用于确保使用基类指针删除派生类对象时,会始终正确地调用派生类的析构函数。当使用基类指针指向派生类对象并进行delete操作时,如果基类的析构函数不是虚的,将只会调用基类的析构函数,而派生类的析构函数不会被调用,可能导致资源泄漏。
-
运行时类型识别(Run-time Type Identification,RTTI):RTTI允许在运行时检查和识别对象的实际类型。C++中的两个RTTI运算符是dynamic_cast和typeid。dynamic_cast用于安全地将基类指针或引用转换为派生类指针或引用,typeid用于返回对象类型的信息。
-
虚函数表(Virtual Function Table,vtable):当一个类包含虚函数时,编译器会为该类创建一个虚函数表,也称为vtable。vtable是一个函数指针数组,存储了虚函数的地址。每个对象拥有一个虚函数表指针,指向该对象所属类的虚函数表。通过虚函数表,实现了在运行时动态查找和调用正确的虚函数。
2. 面向对象有哪些原则
面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它基于对象的概念,通过封装、继承和多态来组织代码。面向对象编程中有一些重要的原则和理念,以下是其中一些常见的原则:
-
单一职责原则(Single Responsibility Principle,SRP):一个类应该只有一个引起它变化的原因,即一个类应该只有一个职责。这个原则指导我们将功能拆分到小而清晰的类中,使每个类只负责一个明确定义的任务。
-
开放封闭原则(Open-Closed Principle,OCP):软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这个原则鼓励使用抽象和接口来定义可扩展的模块,而避免修改现有代码。
-
里氏替换原则(Liskov Substitution Principle,LSP):任何基类的实例都可以被其派生类的实例替换而不改变程序的正确性。这个原则强调继承关系的正确使用,派生类应该能够无缝地被用于基类的场景。
-
接口隔离原则(Interface Segregation Principle,ISP):客户端不应该被迫依赖它们不使用的接口。该原则鼓励设计小而专注的接口,而不是一个臃肿庞大的接口,从而提高代码的内聚性和可维护性。
-
依赖倒置原则(Dependency Inversion Principle,DIP):高层模块不应该直接依赖低层模块,而是依赖于抽象。这个原则强调使用抽象(接口或抽象类)来定义模块之间的依赖关系,降低模块间的耦合性。
-
迪米特法则(Law of Demeter,LoD):一个对象应该对其他对象尽量少的了解。这个原则鼓励尽量将对其他对象的依赖限制在最小范围内,通过封装和间接访问来降低对象之间的耦合度。
这些原则都旨在帮助设计和构建具有高内聚性、低耦合性和易于维护的面向对象系统。当我们在实践中遵守这些原则时,可以提高代码的可扩展性、重用性和可维护性,以及减少错误和改动的影响范围。
3. 面向对象和基于对象的编程思想是什么?
-
面向对象编程 (OOP):
-
OOP 是一种编程范式,它将数据(称为对象)和操作数据的方法(称为方法或函数)组合在一起,以创建一个具有特定行为和属性的对象。OOP 的核心概念包括类、对象、继承、封装和多态。
-
OOP 中,数据和方法通常封装在类中,类是对象的模板,对象是类的实例。通过类,可以创建多个对象,每个对象具有相同的属性和方法,但其数据可能不同。
-
OOP 的主要目标是模拟现实世界中的实体和它们之间的关系,以更容易地设计和维护复杂的系统。
-
-
基于对象编程 (Object-Based Programming):
-
基于对象编程是一种相对简化的编程思想,它强调使用对象来组织和处理数据,但不一定涉及到所有的面向对象编程概念。
-
基于对象编程可以包含类和对象,但不一定包括继承和多态等高级概念。通常,它更关注对象的创建、属性设置和方法调用,而不涉及复杂的继承层次和多态行为。
-
总结:面向对象编程是一种更全面、更复杂的编程范式,它涵盖了面向对象思想的所有核心概念,包括继承、封装、多态等。基于对象编程则是一种更简单的编程思想,更侧重于使用对象来组织和处理数据,但不一定涉及到所有的面向对象概念。选择哪种编程思想取决于项目的需求和复杂性。