简述什么是C++ 动态联编与静态联编 ?
参考答案:
在C++中,联编(Linking)是编译器在程序执行期间确定函数调用或对象引用的具体实现或定义的过程。这涉及到解析标识符(如函数名或变量名)以找到它们在内存中的确切位置。C++支持两种类型的联编:静态联编(Static Linking)和动态联编(Dynamic Linking)。
-
静态联编(Static Linking):
- 发生在编译时:在编译阶段,编译器就确定了函数调用或对象引用的确切位置。
- 与函数重载和模板实例化有关:由于这些特性在编译时就可以确定,所以它们通常使用静态联编。
- 不依赖于运行时类型信息(RTTI):静态联编不需要运行时检查来确定对象或函数的类型。
- 性能开销小:因为联编在编译阶段完成,运行时没有额外的开销。
- 示例:
cpp`void foo(int); void foo(double); int main() { foo(10); // 静态联编,编译器知道要调用哪个foo }`
-
动态联编(Dynamic Linking):
- 发生在运行时:在程序执行期间,根据对象的实际类型来确定函数调用或对象引用的确切位置。
- 与虚函数和继承有关:虚函数是动态联编的关键,它允许子类重写父类中的函数,并在运行时根据对象的实际类型调用正确的函数。
- 依赖于运行时类型信息(RTTI):为了支持动态联编,C++编译器会为每个类生成一个虚函数表(vtable),并在运行时使用它来查找正确的函数实现。
- 性能开销较大:因为需要在运行时进行额外的检查,所以动态联编通常比静态联编慢。
- 示例:
cpp`class Base { public: virtual void foo() { std::cout << "Base foo" << std::endl; } }; class Derived : public Base { public: void foo() override { std::cout << "Derived foo" << std::endl; } }; void callFoo(Base* obj) { obj->foo(); // 动态联编,运行时确定调用哪个foo } int main() { Base b; Derived d; callFoo(&b); // 输出 "Base foo" callFoo(&d); // 输出 "Derived foo" }`
这两种联编方式各有优缺点,应根据具体需求选择合适的联编策略。