面试题答案
一键面试静态联编
- 概念:静态联编是在编译阶段就确定了函数调用与函数实现之间的关系,也称为早期绑定。编译器在编译时,根据对象的类型来确定调用哪个函数。
- 实现方式:通过函数重载和运算符重载来实现。在编译期间,编译器根据函数参数的类型和个数来选择合适的函数版本。例如对于函数
void func(int);
和void func(double);
,编译器依据传入参数类型决定调用哪个。 - 应用场景:适用于在编译期就能确定要调用哪个函数的场景,比如一些基础的工具函数,像数学计算函数等,编译时明确函数版本可提高执行效率。
动态联编
- 概念:动态联编是在运行阶段才确定函数调用与函数实现之间的关系,也叫晚期绑定。程序在运行时根据对象的实际类型来决定调用哪个虚函数。
- 实现方式:通过虚函数和指针或引用实现。当使用基类指针或引用调用虚函数时,实际调用的函数是指针或引用所指向对象的实际类型的虚函数版本。这依赖于虚函数表(vtable)和虚指针(vptr)机制,每个包含虚函数的类都有一个虚函数表,对象内部有一个虚指针指向该虚函数表,运行时根据虚指针找到对应的虚函数。
- 应用场景:常用于实现多态性,在面向对象设计中,当需要根据对象的实际类型执行不同操作时使用。比如在图形绘制系统中,基类
Shape
有虚函数draw
,Circle
、Rectangle
等子类继承Shape
并重写draw
函数,通过基类指针或引用调用draw
函数时,运行时根据实际对象类型决定绘制圆形还是矩形。
两者差异举例
#include <iostream>
class Base {
public:
// 虚函数,用于动态联编
virtual void print() {
std::cout << "This is Base class" << std::endl;
}
// 普通函数,用于静态联编
void show() {
std::cout << "Base show" << std::endl;
}
};
class Derived : public Base {
public:
void print() override {
std::cout << "This is Derived class" << std::endl;
}
void show() {
std::cout << "Derived show" << std::endl;
}
};
int main() {
Base baseObj;
Derived derivedObj;
// 静态联编
baseObj.show();
derivedObj.show();
Base* basePtr = &baseObj;
// 动态联编
basePtr->print();
basePtr = &derivedObj;
// 动态联编,根据实际对象类型调用 Derived 的 print 函数
basePtr->print();
return 0;
}
在上述代码中,show
函数通过对象调用,属于静态联编,编译时就确定调用哪个函数。而 print
函数通过基类指针调用,属于动态联编,运行时根据指针实际指向的对象类型决定调用哪个 print
函数版本。