面试题答案
一键面试编译时期确定函数地址
- 解析:在静态关联(也叫早期绑定)中,函数调用的地址在编译时期就被确定。编译器根据对象的静态类型(即声明时的类型)来决定调用哪个函数。这意味着编译器可以确切知道要调用的函数实体,因为它在编译时就已明确。
- 优势:由于函数地址提前确定,在运行时无需额外的计算或查找来定位函数,这使得代码执行更加高效。
函数调用开销
- 解析:静态关联下函数调用开销相对较小。因为函数地址在编译期确定,在生成的机器码中,函数调用指令直接指向目标函数的地址。相比于动态关联(晚期绑定,运行时才确定函数地址),它不需要额外的机制(如虚函数表的查找)来确定调用的函数。
- 优势:这减少了运行时的开销,特别是在性能关键的代码段,频繁的函数调用可以更快速地执行。
举例说明
#include <iostream>
class Base {
public:
void print() {
std::cout << "Base::print()" << std::endl;
}
};
class Derived : public Base {
public:
void print() {
std::cout << "Derived::print()" << std::endl;
}
};
int main() {
Base b;
Derived d;
b.print(); // 静态关联,编译期确定调用Base::print()
d.print(); // 静态关联,编译期确定调用Derived::print()
Base* ptr = &d;
ptr->print(); // 这里依然是静态关联,根据ptr的静态类型Base,调用Base::print()
return 0;
}
在上述代码中,b.print()
和 d.print()
都是静态关联,编译器在编译时就知道分别调用 Base::print()
和 Derived::print()
。而 ptr->print()
尽管 ptr
指向 Derived
对象,但由于 ptr
的静态类型是 Base
,所以还是调用 Base::print()
,这体现了静态关联根据静态类型确定函数调用的特性,并且这种调用方式在编译期确定函数地址,函数调用开销小。