#include <stdio.h>
#include <stdlib.h>
#include <string.h>
class A{
protected:
virtual void fun(){
printf("class:a function:fun\n");
}
virtual void fun2(){
printf("class:a function:fun2\n");
}
};
class B:public A{
protected:
void fun(){
printf("class:b function:fun\n");
}
void fun2(){
printf("class:b function:fun2\n");
}
};
int main(){
//输入和输出重定向
freopen("in.txt","r", stdin);
freopen("out.txt", "w", stdout);
void (*fun)(A*);
A* pa = new B();
long fp;
memcpy(&fp, pa, 4);
memcpy(&fun, reinterpret_cast<long*>(fp), 4);
fun(pa);
memcpy(&fun, reinterpret_cast<long*>(fp)+1, 4);
fun(pa);
delete pa;
return 0;
}
输出结果如下:
class:b function:fun
class:b function:fun2
百度百科的解释:
void (*fun)(A*); 这段定义了一个
函数指针名字叫做fun,而且有一个A*类型的参数,这个函数指针待会儿用来保存从vtbl里取出的函数地址
A* p=new B(); new B是向内存(内存分5个区:全局名字空间,自由存储区,寄存器,代码空间,栈)自由存储区申请一个内存单元的地址然后隐式地保存在一个
指针中.然后把这个地址赋值给A类型的指针P.
.
long fp; 这个long类型的
变量待会儿用来保存vptr的值
memcpy(&fp,pa,4); 前面说了,他们的实例对象里只有vptr
指针,所以我们就放心大胆地把pa所指的4bytes内存里的东西复制到fp中,所以复制出来的4bytes内容就是vptr的值,即vtbl的地址
现在有了vtbl的地址了,那么我们现在就取出vtbl第一个slot里的内容
memcpy(&fun, reinterpret_cast<long*>(fp), 4); 取出vtbl第一个slot里的内容,并存放在
函数指针fun里。需要注意的是fp里面是vtbl的地址,但fp不是
指针,所以我们要把它先转变成指针类型
fun(pa); 这里就调用了刚才取出的函数地址里的函数,也就是调用了B::fun()这个函数,也许你发现了为什么会有参数p,其实类
成员函数调用时,会有个this
指针,这个p就是那个this指针,只是在一般的调用中
编译器自动帮你处理了而已,而在这里则需要自己处理
分享到:
相关推荐
然而,这里有一个陷阱:如果通过子类对象直接调用父类的虚函数,编译器会认为是在调用子类自身的实现,即使子类没有覆盖这个虚函数。这就是“子类对象不能调用父类中的虚函数”的含义。例如,假设我们有以下代码: ...
本文旨在探讨C++中的虚函数调用机制,通过分析一个简单的示例程序,解释虚函数如何在运行时被正确地调用,并深入剖析这一过程背后的原理。 #### C++中的虚函数调用机制 C++中的虚函数调用机制主要依赖于虚拟表...
在C++中,成员函数的指针是个...但对成员函数来说,常规类型转换是通不过编译的,调用的时候也必须采用特殊的语法。C++专门为成员指针准备了三个运算符: "::*"用于指针的声明,而"->*"和".*"用来调用指针指向的函数。
在上面的代码中,虽然没有直接展示虚函数表,但其工作原理如下:`base_class`、`drived_class1`和`drived_class2`每个类都有自己的vtable,`pbc`指向不同对象时,调用虚函数实际上是在访问相应的vtable并执行相应的...
在C++中,虚函数(Virtual Function)是一种特殊类型的成员函数,它允许基类指针或引用指向派生类对象,并通过该基类指针或引用调用派生类中重写的同名函数。这种机制支持了多态性,即一个接口多种行为。 虚函数的...
虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数,而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。...
这就涉及到了在派生类的构造函数中调用基类构造函数的知识点。 首先,每个类都有一个构造函数,它在对象创建时自动执行,用于初始化类的数据成员。当派生类创建时,它的构造函数会先于派生类的任何其他操作调用基类...
虚函数是C++中面向对象编程的一个重要特性,它允许我们通过基类指针或引用调用派生类中的重写方法,实现多态性。本文将深入探讨如何使用C++实现虚函数,包括虚函数的基本用法、虚析构函数的概念以及如何计算类的大小...
构造函数不能是虚函数,因为构造函数在对象创建时被调用,而此时虚函数表还未初始化。 7. **C++11的final关键字**: 从C++11开始,可以使用`final`关键字阻止子类进一步覆盖虚函数: ```cpp class Base { ...
在类继承层次中,如果基类的虚函数在派生类中被重定义(覆盖),那么派生类的VTABLE将会包含它自己版本的虚函数地址,而基类的VTABLE仍然保留原有的地址。这保证了不论对象实际属于哪个类,调用虚函数都会执行相应类...
2. 虚函数在基类中声明,目的是提供一个统一的接口,即便在派生类中被重定义,基类指针仍然可以通过虚函数调用派生类的方法。 3. 派生类可以重新定义基类的虚函数,但函数签名(返回类型、函数名、参数列表)必须...
在一个类的成员函数中,可以直接调用本类的其他成员函数,也可以通过对象或指针间接调用其他类的成员函数。例如,我们有`ClassA`和`ClassB`两个类,`ClassA`中有一个成员函数`funcA()`,`ClassB`中有一个成员函数`...
本文将详细解释友元类的调用实例,包括友元类的定义、继承关系、成员访问控制和虚函数调用机制。 友元类的定义 在上面的代码中,类 A 声明为类 B 的友元类,使用关键字 `friend`。这意味着类 A 可以访问类 B 的...
总结来说,这个测试用例主要关注虚函数在C++中的作用,包括多态性、动态绑定、抽象类和接口设计、资源管理以及虚函数表的工作原理。通过一系列的例子和测试,我们可以深入理解虚函数如何提升代码的灵活性和可扩展性...
在C++中,虚函数的主要作用是实现多态性,即允许父类型的指针或引用调用子类重写的成员函数。这种机制使得程序员能够编写更灵活、可扩展的代码。例如: ```cpp class Base { public: virtual void func() { cout ;...
remote-function支持调用普通函数,也支持调用类的成员函数。 remote-function底层使用命令管道进行通讯,内置的流程完成了函数参数和返回值的序列化过程。且大部分的参数和返回值都可以使用内置的(反)序列化方法...
当一个函数在基类中声明为虚函数时,子类可以重写这个函数,并且在运行时,通过基类指针或引用调用该函数时,会根据实际对象的类型调用相应的实现,这就是动态绑定或运行时多态。虚函数的这种特性使得虚函数在很多...
它允许我们使用基类类型的指针或者引用指向派生类的对象,从而在运行时决定调用哪个方法。这种灵活性的核心在于虚函数及其虚函数表。 假设我们有一个基类`ClassA`和一个继承自`ClassA`的派生类`ClassB`,并且`...
构造函数:不可以虚化(重写),在子类的构造函数前自动被调用一次父类的构造函数. 析构函数:当[DELETE]类指针时 非虚会从[此类]一直释放到基类,为虚时会从被赋于的[NEW类]的析构函数一直释放到基类. 总得来说释放[方向...
在销毁对象时,如果对象是通过基类指针或引用删除的,而对象实际上是派生类的实例,那么非虚析构函数只会调用基类的析构函数,派生类的析构函数不会被调用,可能会导致内存泄漏或资源未释放的问题。虚析构函数则能...