virtual函数

对于virtual函数,若派生类别改写了,则调用派生类别之virtual函数;

若派生类别没有改写,则调用基础类别之virtual函数;

另:两者均存在于内存中,差别只是在于vt中的函数指针指向不同的地址!

看到一个类别或是实例,首先想到了什么,当然是内存布局!

你所追求的生活方式是什么; 

你所向往的生活方式又是什么!

### C++ 中虚函数的行为与调试问题 虚函数机制是 C++ 实现运行时多态的核心机制之一。在对象模型中,每个具有虚函数的类都会有一个虚函数表(vtable),该表中保存了虚函数的地址,对象通过一个指针(vptr)指向其所属类的虚函数表。当调用虚函数时,程序通过 vptr 找到对应的虚函数表,再从中查找函数地址并调用。 在虚函数表中,如果某个函数是纯虚函数(即没有实现的虚函数),传统上 C++ 编译器会为其在虚函数表中放置一个特殊的函数指用以处理错误调用,例如打印“Pure virtual function called”并导致程序崩溃[^1]。这种机制确保在运行时调用未实现的纯虚函数时能立即发现问题。 虚函数的另一个常见问题是虚函数在构造函数或析构函数中的调用行为。在构造派生类对象时,基类构造函数的执行发生在派生类部分之前,此时对象的动态类型仍为基类类型。因此,在基类构造函数中调用虚函数将调用基类的实现,而不是派生类的实现。类似地,在析构函数中调用虚函数也将调用当前对象所属类的函数实现,而不是更派生类的实现。某些编译器(如 Visual C++ 8.0 和 GCC 4.x)会优化掉运行时多态行为,直接调用当前类的函数实现。如果基类的虚函数是纯虚函数且没有定义,链接器将报告错误[^2]。 在调试虚函数调用时,可能会遇到以下问题: - **虚函数表指针(vptr)未正确初始化**:这通常发生在对象构造尚未完成时调用虚函数,或者在析构完成后再次调用虚函数。 - **虚函数表中的函数指针不正确**:可能由于编译器优化、虚函数未实现或虚函数表被破坏导致。 - **断点未命中**:调试器可能无法在虚函数调用链中正确设置断点,尤其是在涉及多态和虚函数表跳转的情况下。 例如,以下代码演示了虚函数的基本行为: ```cpp #include <iostream> using namespace std; class Base { public: virtual void foo() { cout << "Base::foo" << endl; } virtual void bar() = 0; // 纯虚函数 }; class Derived : public Base { public: void foo() override { cout << "Derived::foo" << endl; } void bar() override { cout << "Derived::bar" << endl; } }; int main() { Derived d; Base* b = &d; b->foo(); // 调用 Derived::foo b->bar(); // 调用 Derived::bar return 0; } ``` 在调试上述代码时,如果在 `Base::bar()` 中设置断点,调试器可能不会命中该断点,因为该函数是纯虚函数,实际调用的是 `Derived::bar()`。如果在 `Base` 类中没有为 `bar()` 提供实现,程序将无法链接。如果提供了实现,则在构造函数或析构函数中调用 `bar()` 时,会调用 `Base::bar()`,而不是派生类的实现[^2]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值