C++面试高频(类和对象)
类和对象
1 类的权限有几种? ⭐⭐⭐⭐⭐
类中成员访问属性有三种:
(1)私有成员(变量和函数)只限于类成员访问,由private限定;
(2)公有成员(变量和函数)允许类成员和类外的任何访问,由public限定;
(3)受保护成员(变量和函数)允许类成员和派生类成员访问,不允许类外的任何访问。所以protected对外封闭,对派生类开放。
2 对象是值传递还是引用传递? ⭐⭐⭐⭐⭐
引用传递对象
- 通常,使用对象作为参数的函数时,应按引用而不是按值来传递对象,这样可以有效的提高效率。
原因
- 因为按值传递的时候,将会涉及到调用拷贝构造函数生成临时的拷贝,然后又调用析构函数,这在大型的对象上要比传递引用花费的时间多的多。当我们不修改对象的时候,应当将参数声明为const引用。
3 重载、重写和隐藏的区别 ⭐⭐⭐⭐⭐
重载(Overloading):
- 重载是在同一个作用域内定义多个相同名称但参数列表不同的函数或方法。
- 重载函数可以根据不同的参数数量或类型来执行不同的操作。
- 重载通过函数名和参数列表来区分不同的函数。
举例代码:
#include <iostream> void printNumber(int num) { std::cout << "Integer number: " << num << std::endl; } void printNumber(double num) { std::cout << "Floating-point number: " << num << std::endl; } int main() { printNumber(10); printNumber(3.14); return 0; }
重写(Override):
- 重写是指子类重新定义从父类继承的虚函数,使其具有不同的实现。
- 重写的函数签名(函数名、参数列表和返回类型)必须与被重写函数相同。
- 在运行时,根据具体的对象类型,调用的是子类重写的版本。
举例代码:
#include <iostream> class Base { public: virtual void sayHello() { std::cout << "Hello from Base class!" << std::endl; } }; class Derived : public Base { public: void sayHello() override { // 使用 override 关键字表明重写了父类的函数 std::cout << "Hello from Derived class!" << std::endl; } }; int main() { Base* basePtr = new Derived(); basePtr->sayHello(); // Output: "Hello from Derived class!" delete basePtr; return 0; }
隐藏(Hiding):
- 隐藏是指在派生类中定义与父类具有相同名称的成员函数,使其隐藏父类中的同名函数。
- 隐藏函数与父类的函数没有多态性,只有通过对象的实际类型调用时才会调用相应的函数。
举例代码:
#include <iostream> class Base { public: void sayHello() { std::cout << "Hello from Base class!" << std::endl; } }; class Derived : public Base { public: void sayHello() { std::cout << "Hello from Derived class!" << std::endl; } }; int main() { Base baseObj; Derived derivedObj; baseObj.sayHello(); // Output: "Hello from Base class!" derivedObj.sayHello(); // Output: "Hello from Derived class!" Base* basePtr = new Derived(); basePtr->sayHello(); // Output: "Hello from Base class!" delete basePtr; return 0; }
4 简述面向对象的三大特性⭐⭐⭐⭐
面向对象编程(OOP)的三大特性是封装、继承和多态。下面对每个特性进行简要说明:
封装(Encapsulation):
- 封装是将数据和操作封装在一个单元(类)中的机制。
- 通过封装,实现类的成员变量和成员函数作为一个整体进行管理和操作。
- 封装隐藏了数据的具体实现细节,只暴露出必要的接口,提供了更好的安全性和可维护性。
- 通过访问修饰符(公有、私有、保护),控制对类的成员的访问权限。
继承(Inheritance):
- 继承是通过创建派生类来扩展和重用已有类的机制。
- 基类(父类)是已经定义的类,派生类(子类)继承了基类的属性和方法。
- 子类可以自定义新的属性和方法,也可以覆盖或扩展继承的父类的属性和方法。
- 继承实现了类与类之间的关系,实现了代码的重用和扩展。
多态(Polymorphism):
- 多态是指同一个接口可以由不同的对象以不同的方式进行实现和响应的能力。
- 多态允许使用基类的指针或引用来引用派生类的对象,实现了多种形态的使用。
- 编译时多态使用函数重载和运算符重载;运行时多态通过虚函数实现(动态绑定)。
- 多态提高了代码的灵活性和可扩展性,使得程序更具有可读性和可维护性。
5 什么是多态?⭐⭐⭐⭐
利用虚函数,基类指针指向基类对象时就使用基类的成员(包括成员函数和成员变量),指向派生类对象时就使用派生类的成员。 基类指针可以按照基类的方式来做事,也可以按照派生类的方式来做事,它有多种形态,或者说有多种表现方式,我们将这种现象称为多态。
代码举例:
#include <iostream> class Base { public: virtual void print() { std::cout << "This is the Base class" << std::endl; } }; class Derived : public Base { public: void print() override { std::cout << "This is the Derived class" << std::endl; } }; int main() { Base* basePtr; Base baseObj; Derived derivedObj; basePtr = &baseObj; basePtr->print(); // 此时使用基类的成员函数来打印消息 basePtr = &derivedObj; basePtr->print(); // 此时使用派生类的成员函数来打印消息 return 0; }
6 继承和虚继承⭐⭐⭐⭐
继承是面向对象编程中的一个重要概念,它允许一个类(派生类或子类)继承另一个类(基类或父类)的属性和方法。通过继承,派生类可以重用基类的代码,并可以在此基础上进行扩展和修改。
继承可以通过以下方式进行:
公有继承(public inheritance):使用public
关键字来指定基类与派生类之间的继承关系。公有继承表示派生类可以访问基类的公有成员。例如:
class Base { public: int x; }; class Derived : public Base { public: int y; }; 在这个例子中,Derived类公有继承了Base类,因此它可以访问Base类中的公有成员变量x。
保护继承(protected inheritance):使用protected
关键字来指定基类与派生类之间的继承关系。保护继承表示派生类可以访问基类的公有和保护成员。例如:
class Base { protected: int x; }; class Derived : protected Base { public: int y; }; 在这个例子中,Derived类保护继承了Base类,因此它可以访问Base类中的公有和保护成员变量x。
私有继承(private inheritance):使用private
关键字来指定基类与派生类之间的继承关系。私有继承表示派生类可以访问基类的公有和保护成员。例如:
class Base { private: int x; }; class Derived : private Base { public: int y; }; 在这个例子中,Derived类私有继承了Base类,因此它可以访问Base类中的公有和保护成员变量x。
虚继承(virtual inheritance)是处理多重继承下的二义性问题的一种机制。当一个派生类通过不同的路径继承自同一个基类时,使用虚继承可以确保只有一个基类子对象被创建。例如:
class Base { public: int x; }; class Derived1 : public virtual Base { public: int y; }; class Derived2 : public virtual Base { public: int z; }; class Derived3 : public Derived1, public Derived2 { public: int sum; }; 在这个例子中,Derived3类通过虚继承方式从Derived1和Derived2类继承Base类,确保只有一个Base子对象被创建,避免了多个实例的问题。
7 多态的类,内存布局是怎么样的 ⭐⭐⭐⭐⭐
多态是面向对象
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
该专栏面向嵌入式开发工程师、C++开发工程师,包括C语言、C++,操作系统,ARM架构、RTOS、Linux基础、Linux驱动、Linux系统移植、计算机网络、数据结构与算法、数电基础、模电基础、5篇面试题目、HR面试常见问题汇总和嵌入式面试简历模板等文章。超全的嵌入式软件工程师面试题目和高频知识点总结! 另外,专栏分为两个部分,大家可以各取所好,为了有更好的阅读体验,后面会持续更新!!!