今天接触到一道面试题,提供一个类,含有两个私有变量和一个virtual的析构函数,没有提供任何获取私有变量的公共方法,让提取私有变量。代码大致如下:
class A { public: A(){} virtual ~A(){} private: int n; double f; };
我认为核心思路是利用C++的内存对象模型来提取,但是虚表指针(vptr)的位置因编译器的不同而不同,即要么放在最前面,要么放在最后面。所以上面的类A的内存模型可能为:
由于虚表指针(vptr)的位置不定,所以我们只有在确定了虚表指针位置后才能定位到私有变量的位置。我们可以利用C++的public成员变量在类中的索引来确定当前编译器将类的虚表指针放在什么位置了,所以需要先写一段测试代码:
class Test { public: int n; virtual ~Test(){} }; /*判断虚表指针是否在最前面*/ bool isVptrAhead() { bool bAhead = false; int Test::* itIndex = &Test::n; char cIndex[2]; memset(cIndex, 0, 2); sprintf(cIndex, "%d", itIndex); int iIndex = atoi(cIndex); if(iIndex == 0) { bAhead = true; } return bAhead; }
上面这段代码即可以测试虚表指针是放在前面的还是后面的。好了,至此,我们可以回来解决最开始的问题了,提取私有变量。代码如下:
A a; void* pA = (void*)&a; if(isVptrAhead()) { int n = *(int*)((char*)pA+sizeof(int)); double f = *(double*)((char*)pA + 2*sizeof(int)); }else { int n = *(int*)pA; double f = *(double*)((char*)pA + sizeof(int)); }
这道题还有另外一种解决方式,即利用reinterpret_cast的特性,写一个和A一样的B,只是将private改为public,实现如下
class B { public: B(){} virtual ~B(){} public: int n; double f; };
使用如下:
A a; B* pB = reinterpret_cast<B*>(&a); pB->n; pB->f;
相关推荐
`)是不提供具体实现的虚函数,包含纯虚函数的类称为抽象类,不能直接实例化。抽象类主要用于作为基类,为派生类提供接口。 12. 函数覆盖(Override):当派生类中的函数与基类的虚函数具有相同的名称和参数列表时...
- 在含有虚函数的类中,每个对象都有一个虚表指针,虚表包含了类中所有虚函数的地址。这样,通过虚函数调用,即使指针类型是基类,也可以调用派生类的相应实现。 7. **赋值函数**: - 通常用于对象之间的值复制,...
C++通过虚函数和纯虚函数实现多态,子类可以重写基类的虚函数,实现功能的扩展。 11. **静态成员**:静态成员属于类,而非对象,所有对象共享同一份静态成员。静态成员函数不能访问非静态成员,但可以直接调用其他...
这份C++期末复习资料涵盖了C++语言的多个方面,包括函数重载、类和对象、构造函数和析构函数、友元函数、继承和派生、虚函数、纯虚函数和抽象类等,为C++初学者和有一定基础的人群提供了很好的参考资料。
`Time`类有三个构造函数:默认构造函数(不传参数)、带有三个参数的构造函数和带有一个参数的构造函数(拷贝构造)。析构函数`~Time()`在对象生命周期结束时调用,通常用于释放资源。在这个例子中,析构函数简单地...
- **虚函数**: 带有 `virtual` 关键字的成员函数,使得基类中的虚函数可以在派生类中重新定义。 - **多态**: 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在C++中通过虚函数实现。 - **多态的...
10. 虚函数:虚函数是一种特殊的成员函数,它可以被派生类覆盖。虚函数可以使得基类提供一个接口,而不需要提供实现体。 例如,基类中可以定义一个虚函数,派生类可以提供自己的实现体。 11. 多态性:多态性是一种...
C++ 语言支持多态的实现通过虚函数和纯虚函数。 虚函数和纯虚函数 虚函数是指可以被继承的函数。纯虚函数是指不能被继承的函数。 抽象类 抽象类是指包含纯虚函数的类。抽象类不能被实例化,必须被继承。 函数...
C++编程语言的知识点在给定的复习资料中主要涵盖了函数重载、构造函数与析构函数、访问控制、友元、动态绑定和虚函数、抽象类与纯虚函数、继承与派生等方面。 1. **函数重载**:函数重载是C++中允许同一作用域内...
5. 虚函数:虚函数是C++实现多态性的一个关键特性,它可以允许通过基类指针或引用调用派生类的重写版本。虚函数不能是静态成员函数,因为静态成员函数与特定对象无关。 6. 运算符重载:C++允许重载运算符,但重载...
通过继承,一个类(子类或派生类)可以从另一个类(基类或父类)中获取属性和行为。这使得代码重用成为可能,同时也可以通过多态性(即一个接口,多种实现)来增强程序的灵活性。 多态性是C++的另一大亮点。它包括...
- 类`MyClass`有一个带有初始化列表的构造函数,但C++会自动提供默认构造函数(如果用户未定义),以及一个拷贝构造函数。因此,类`MyClass`实际上有2个构造函数。 8. **静态成员函数与常量成员函数**: - 静态...
7. **虚函数**:虚函数使得基类的指针或引用来调用派生类的函数成为可能,实现了多态性。第七题中,当一个函数被声明为`virtual`,在派生类中它仍然是虚函数,选项A正确。 8. **构造函数的调用**:当创建类的对象时...
第七题涉及到了虚函数,当在类中声明一个函数为`virtual`时,这个函数在该类的所有派生类中都会是虚函数,允许动态绑定。 第八题中,执行`AB x:`这样的语句会调用无参构造函数来初始化`AB`类型的对象`x`。 第九题...
析构函数则是用于撤销对象时执行清理工作,每个类只能有一个析构函数,并且它不能带有参数。 2. 友元:友元函数是类的非成员函数,可以访问类的私有成员。其主要作用是为了方便某些操作,突破面向对象设计中的封装...
- 名称前带有波浪线(~)。 - 无参数。 - 不可重载。 - 主要用于清理对象在使用过程中创建的资源。 3. **拷贝构造函数**:拷贝构造函数用于创建一个已存在对象的副本。它的特点包括: - 同名于类,但有一个...
它的名字前带有波浪线 (~),没有参数,不能重载。 3. **拷贝构造函数**: - 拷贝构造函数用于初始化一个新对象为已存在对象的副本。它接受一个类类型的引用作为参数,用于深拷贝或浅拷贝对象的内容。拷贝构造函数...
在上述的C++上机实验报告中,涉及了多个面向对象编程的关键概念,包括类和对象的定义、构造函数和析构函数、静态成员、友元函数和友元类、派生类以及虚函数。以下是对这些概念的详细解释: 1. **类和对象**: 类是...
根据给定的文件信息,我们可以总结出一系列关于C++编程语言的重要知识点,这些知识点主要涵盖了C++中的构造函数、友元、成员访问控制、析构函数、重载函数、继承和虚函数等核心概念。 ### 构造函数 1. **无参构造...