对含有virtual function的class求sizeof

本文通过一个C++示例程序介绍了虚函数表的工作原理,包括不同类的虚函数如何组织,以及多重继承中虚函数表的实现方式。通过断点调试展示了不同类实例大小的变化及其原因。
#include <iostream>
using namespace std;

class A
{
public:
	virtual void func_1() {}
	virtual void func_2() {}
	virtual ~A() {}
};

class B
{
public:
	virtual void func_3() {}
};

class C : public B
{
public:
	virtual void func_3() {}// 覆盖
	virtual void func_4() {}
};

class D : public A, public B
{
public:
	virtual void func_1() {}
	virtual void func_5() {}
};

int main()
{
	// 断点调试查看虚表
	A a;
	B b;
	C c;
	D d;

	
	cout << "sizeof(A) = " << sizeof(A) << endl;//sizeof(A) = 4,因为无论有多少虚函数,A实例只有一个指向虚表的指针
	cout << "sizeof(B) = " << sizeof(B) << endl;//sizeof(A) = 4,理由同上
	cout << "sizeof(C) = " << sizeof(C) << endl;//sizeof(A) = 4,单一继承
	cout << "sizeof(D) = " << sizeof(D) << endl;//sizeof(A) = 8,多重继承,D有两张虚表,也有两个执行项虚表的指针,所以为8
	cin.get();
}


断点调试时内存模型:



<think>我们面临的核心挑战:在纯C工程(由CCS创建)中集成C++类,并通过C代码调用其成员函数。由于C语言不支持类,我们必须通过中间层封装来暴露C++对象的功能。###解决方案概述1.**封装层设计**:创建C风格的包装函数,这些函数将:-通过指针操作C++对象(将对象指针视为`void*`)-提供对象的创建、销毁和成员函数调用的接口2.**类型安全与内存管理**:确保C代码仅通过我们提供的接口操作对象3.**编译环境配置**:确保CCS工程能同时编译C和C++文件(需要确认CCS是否支持混合编译)###具体步骤假设我们有一个C++类`MyClass`定义如下:```cpp//File:MyClass.hppclassMyClass{public:MyClass(intinit_val);~MyClass();intmethod1(intarg);voidmethod2(char*msg);private:intvalue_;};```####步骤1:创建封装接口(C风格头文件)```cpp//File:c_interface.h#ifdef__cplusplusextern"C"{#endif//不透明指针(C代码不知道具体结构,只能通过我们的接口操作)typedefvoid*MyClassHandle;//构造函数封装:返回对象句柄MyClassHandlecreateMyClass(intinit_val);//析构函数封装voiddestroyMyClass(MyClassHandlehandle);//成员函数封装intMyClass_method1(MyClassHandlehandle,intarg);voidMyClass_method2(MyClassHandlehandle,char*msg);#ifdef__cplusplus}#endif```####步骤2:实现封装函数(C++源文件)```cpp//File:c_interface.cpp#include"c_interface.h"#include"MyClass.hpp"extern"C"{MyClassHandlecreateMyClass(intinit_val){//显式构造对象并返回指针(需转换为void*)returnstatic_cast<void*>(newMyClass(init_val));}voiddestroyMyClass(MyClassHandlehandle){//将void*转换回MyClass*后删除deletestatic_cast<MyClass*>(handle);}intMyClass_method1(MyClassHandlehandle,intarg){autoobj=static_cast<MyClass*>(handle);returnobj->method1(arg);}voidMyClass_method2(MyClassHandlehandle,char*msg){autoobj=static_cast<MyClass*>(handle);obj->method2(msg);}}```####步骤3:在C代码中使用```c//File:main.c#include"c_interface.h"intmain(){//创建对象MyClassHandleobj=createMyClass(42);//调用方法intresult=MyClass_method1(obj,10);MyClass_method2(obj,"HellofromC!");//销毁对象destroyMyClass(obj);return0;}```###CCS工程配置关键点1.**添加C++支持**:-将`.cpp`文件添加到工程(CCS需启用C++编译器)-检查工程属性中的编译器选项:确保使用C++编译器编译`.cpp`文件2.**链接器配置**:-可能需要指定C++标准库(如`libstdc++.a`)-避免名称修饰冲突:确保封装函数使用`extern"C"`3.**头文件包含路径**:-包含`c_interface.h`的目录需添加到INCLUDE路径###潜在问题与解决1.**内存管理**:-C代码必须严格配对调用`create/destroy`,避免内存泄漏-建议在C++端使用`shared_ptr`管理对象生命周期(需谨慎处理跨语言所有权)2.**异常处理**:-如果C++成员函数可能抛出异常,必须在封装函数内捕获:```cppintMyClass_method1(MyClassHandlehandle,intarg){try{autoobj=static_cast<MyClass*>(handle);returnobj->method1(arg);}catch(...){//返回错误代码或记录日志return-1;}}```3.**类型安全**:-使用不透明指针(`void*`)时,禁止C代码直接解引用###替代方案:纯虚接口如果对运行时开销敏感,可改用纯虚基类定义接口:```cpp//File:IMyInterface.hclassIMyInterface{public:virtual~IMyInterface(){}virtualintmethod1(intarg)=0;virtualvoidmethod2(char*msg)=0;};//工厂函数(extern"C")extern"C"IMyInterface*createImplementation(intinit_val);```C++实现类继承该接口,C代码通过虚表调用(但仍有RTTI开销)。###最终建议1.**简化接口**:尽量减少跨越语言边界的方法调用2.**数据传递**:使用C兼容类型(POD结构、基本类型)3.**测试**:先在PC环境验证混合编译后再移植到CCS§§相关问题§§1.CCS是否默认支持C/C++混合编译?如何验证?2.如果C++类使用了模板,封装层该如何处理?3.如何调试此类混合语言项目中的内存错误(如堆损坏)?</think> 在 CCS 开发的纯 C 工程中集成 C++ 类需要特殊的接口设计,以下是完整实现方案: ### 解决方案核心:创建 C 接口封装层 由于 C 语言无法直接识别类结构,需要构建中间封装层来包装 C++ 对象的功能。以下是推荐的实现流程(示例以 `Function` 类为例): #### 1. C++ 源文件实现(function.cpp) ```cpp #include "function.h" class FunctionImpl { public: FunctionImpl(int init_val) : value(init_val) {} int getValue() const { return value; } void setValue(int v) { value = v; } double processData(double input) { return input * value; } private: int value; }; // C 接口实现 extern "C" { FunctionHandle create_function(int init_val) { return reinterpret_cast<FunctionHandle>(new FunctionImpl(init_val)); } void destroy_function(FunctionHandle handle) { delete reinterpret_cast<FunctionImpl*>(handle); } int get_value(FunctionHandle handle) { return reinterpret_cast<FunctionImpl*>(handle)->getValue(); } void set_value(FunctionHandle handle, int new_val) { reinterpret_cast<FunctionImpl*>(handle)->setValue(new_val); } double process_data(FunctionHandle handle, double input) { return reinterpret_cast<FunctionImpl*>(handle)->processData(input); } } ``` #### 2. C 兼容头文件(function.h) ```cpp #ifdef __cplusplus extern "C" { #else typedef void* FunctionHandle; // 避免 C 报错 #endif // 类型定义(C/C++ 共享) typedef struct FunctionHandle* FunctionHandle; // C 接口声明(extern "C" 确保 C 可识别) #if defined(__cplusplus) FunctionHandle create_function(int init_val); #else struct FunctionHandle* create_function(int init_val); #endif void destroy_function(FunctionHandle handle); int get_value(FunctionHandle handle); void set_value(FunctionHandle handle, int new_val); double process_data(FunctionHandle handle, double input); #ifdef __cplusplus } #endif ``` #### 3. C 文件调用示例(main.c) ```c #include "function.h" // 包含封装头文件 int main() { // 创建对象(通过封装接口) FunctionHandle func = create_function(5); // 调用成员函数 set_value(func, 10); double result = process_data(func, 2.5); // 销毁对象 destroy_function(func); return 0; } ``` ### CCS 工程配置关键步骤 1. **添加文件到工程** ```mermaid graph LR A[CCS Project] --> B[添加 function.cpp] A --> C[添加 function.h] A --> D[添加 main.c] ``` 2. **编译器设置**(右键工程 > Properties): - **C++ Compiler:** 启用 C++11 标准(Language standard → C++11) - **Linker:** 添加 C++ 标准库 `libc++.a`(File search path → ${C6000_CGT_DIR}/lib) - **Include Options:** 添加头文件目录 3. **解决 C/C++ 混合链接问题**: ```bash # 修改 link.cmd 文件,强制处理 C++ 符号 -l:libc++.a # TI 编译器链接 C++ 库 --disable_auto_rts # 避免自动运行时库冲突 ``` ### 注意事项与最佳实践 1. **内存管理** - C 代码必须显式调用 `destroy_function` 避免内存泄漏 - 对象生命周期由 C 代码完全控制 2. **类型安全** ```cpp // 在 function.h 中添加类型检查宏 #if defined(__cplusplus) && !defined(__GNUC__) static_assert(sizeof(FunctionHandle) == sizeof(void*), "Handle size mismatch!"); #endif ``` 3. **异常处理** - 在 C++ 封装接口中使用 `try/catch` - 通过返回错误码向 C 传递异常信息 4. **数据结构交换** - 复杂数据传递使用 POD 结构体 ```c struct CData { // C 兼容结构体 int id; float value; }; ``` ### 调试建议 1. 启用 MAP 文件生成(工程属性 > Linker → Advanced options → --map_file) 2. 使用联合调试模式: ``` [Debug Config] Type: Mixed C/C++ Stop at: main (C entry point) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值