📅  最后修改于: 2023-12-03 15:40:17.658000             🧑  作者: Mango
在C++中,虚拟函数和抽象类是两个重要的概念。在面试中,经常会涉及到这两个概念。下面将介绍一些常见的面试问题,并提供相应的回答。
虚拟函数是在基类中声明的函数,并且在派生类中进行重写的函数。它可以通过指向基类对象的指针或引用访问派生类中的特定函数。
在C++中,虚拟函数可以用关键字 virtual 来声明。例如:
virtual void foo();
注意:虚拟函数必须在公共接口中声明,否则无法从派生类中调用。
纯虚拟函数是一个没有实现的虚拟函数。它可以通过在函数声明中加上 "= 0" 来确保它是纯虚拟函数。例如:
virtual void foo() = 0;
注意:纯虚拟函数不能在基类中实现,而是必须在派生类中实现。
抽象类是一个包含至少一个纯虚拟函数的类。抽象类不能被实例化,而必须通过基于该类的派生类来实例化。
抽象类通常作为一个抽象的概念存在,只提供一些接口,并且需要派生类来实现这些接口。
抽象类可以提供一个框架,只需要提供一些接口和抽象方法。这样可以使得代码更加通用和可扩展。
抽象类的一个重要用途是通过这种方式来实现多态性。许多派生类可以从同一个抽象类派生,并实现相同的接口,并且可以通过指向该抽象类对象的指针来访问不同的实现。
虚拟函数是指在基类中声明的函数,而可以在派生类中进行重写。而普通函数则是在类中定义的普通函数。
虚拟函数的主要特点是:在运行时,可以根据对象的实际类型来调用正确版本的函数。因此,虚拟函数可以实现多态性。
在使用指向派生类的基类指针或引用时,需要使用虚拟析构函数。如果析构函数不是虚拟函数,就会出现问题。这是因为按照基类对象的类型进行销毁时,只有基类的析构函数被调用。
因此,如果有一个基类指针或引用,指向的是派生类的实例,而这个基类指针或引用必须在结束时,用delete删除这个实例,那么这个基类必须有虚拟析构函数。
在派生类中,可以通过以下两种方式来调用基类中的函数:
class Base
{
public:
void foo() { cout << "Base::foo()" << endl; }
};
class Derived : public Base
{
public:
void bar() { Base::foo(); } // 调用基类的函数
};
Base* pBase = new Derived();
pBase->foo(); // 调用基类的函数
可以使用关键字 final 来标记虚拟函数,防止在派生类中被重写。例如:
class Base
{
public:
virtual void foo() final;
};
class Derived : public Base
{
public:
// 无法重写Base中的foo函数
};
可以通过将构造函数声明为 protected 来禁止基类的实例化。这样,只有派生类才能调用构造函数来创建类的实例。
class Base
{
protected:
Base() {}
};
class Derived : public Base
{
public:
Derived() {}
};
只要类中有至少一个纯虚拟函数,这个类就是一个抽象类。
class Shape
{
public:
virtual void draw() = 0;
};
抽象类通常是通过基类派生出一系列的派生类来使用。这些派生类必须实现抽象类中所声明的所有纯虚拟函数,否则它们也将成为抽象类。
例如:
class Circle : public Shape
{
public:
void draw() { /* 实现圆形的绘制 */ }
};
class Rectangle : public Shape
{
public:
void draw() { /* 实现矩形的绘制 */ }
};
这些派生类可以通过基类的指针或引用进行访问,也支持使用多态性来访问不同的实现。例如:
Shape* pShape = new Circle();
pShape->draw(); // 调用Circle::draw()
pShape = new Rectangle();
pShape->draw(); // 调用Rectangle::draw()
可以使用 is_base_of 模板来判断一个类是否继承自某个基类。例如:
#include <type_traits>
class Base {};
class Derived : public Base {};
bool isDerivedFromBase = std::is_base_of<Base, Derived>::value; // true
本文介绍了一些关于C++中虚拟函数和抽象类的常见面试问题,涉及虚拟函数、纯虚拟函数、抽象类、基类与派生类之间的关系、多态性等内容。希望对读者有所帮助。