C++空类编译器自动生成的6个成员函数


一、问题

       在C++中,编译器会为空类提供哪些默认成员函数?分别有什么样的功能呢? 

二、详解



1、空类,声明时编译器不会生成任何成员函数


        对于空类,编译器不会生成任何的成员函数,只会生成1个字节的占位符。

        有时可能会以为编译器会为空类生成默认构造函数等,事实上是不会的,编译器只会在需要的时候生成6个成员函数:默认构造函数、默认拷贝构造函数、默认析构函数、默认赋值运算符 这四个是我们通常大都知道的。但是除了这四个,还有两个,那就是取址运算符和 取址运算符 const。

 代码:

[html]  view plain  copy
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class Empty_one  
  5. {  
  6. };  
  7. class Empty_two  
  8. {};  
  9. class Empty_three  
  10. {  
  11.     virtual void fun() = 0;  
  12. };  
  13. class Empty_four :  public Empty_two, public Empty_three  
  14. {  
  15. };  
  16.   
  17. int main()  
  18. {  
  19.   cout<<"sizeof(Empty_one):"<<sizeof(Empty_one)<<endl;  
  20.   cout<<"sizeof(Empty_two):"<<sizeof(Empty_two)<<endl;  
  21.   cout<<"sizeof(Empty_three):"<<sizeof(Empty_three)<<endl;  
  22.   cout<<"sizeof(Empty_four):"<<sizeof(Empty_four)<<endl;  
  23.   return 0;  
  24. }  
运行结果:

分析:

类Empty_one、Empty_two是空类,但空类同样可以被实例化,而每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址,所以sizeof(Empty_one)和sizeof(Empty_two)的大小为1。

类Empty_three里面因有一个纯虚函数,故有一个指向虚函数的指针(vptr),64位系统分配给指针的大小为8个字节,所以sizeof(Empty_three)的大小为8。

类Empty_four继承于Empty_two和Empty_three,编译器取消Empty_two的占位符,保留一虚函数表,故大小为8。



2、空类,定义时会生成6个成员函数


        当空类Empty_one定义一个对象时Empty_one pt;sizeof(pt)仍是为1,但编译器会生成6个成员函数:一个缺省的构造函数、一个拷贝构造函数、一个析构函数、一个赋值运算符、两个取址运算符。

[html]  view plain  copy
  1. class Empty  
  2. {};  
等价于:

[html]  view plain  copy
  1. class Empty  
  2. {  
  3.   public:  
  4.     Empty();                            //缺省构造函数  
  5.     Empty(const Empty &rhs);            //拷贝构造函数  
  6.     ~Empty();                           //析构函数   
  7.     Empty& operator=(const Empty &rhs); //赋值运算符  
  8.     Empty* operator&();                 //取址运算符  
  9.     const Empty* operator&() const;     //取址运算符(const版本)  
  10. };  
使用时的调用情况:

[html]  view plain  copy
  1. Empty *e = new Empty();    //缺省构造函数  
  2. delete e;                  //析构函数  
  3. Empty e1;                  //缺省构造函数                                 
  4. const Empty e2(e1);        //拷贝构造函数  
  5. e2 = e1;                   //赋值运算符  
  6. Empty *pe1 = &e1;          //取址运算符(非const)  
  7. const Empty *pe2 = &e2;    //取址运算符(const)  

C++编译器对这些函数的实现:

[html]  view plain  copy
  1. inline Empty::Empty()                          //缺省构造函数  
  2. {  
  3. }  
  4. inline Empty::~Empty()                         //析构函数  
  5. {  
  6. }  
  7. inline Empty *Empty::operator&()               //取址运算符(非const)  
  8. {  
  9.   return this;   
  10. }             
  11. inline const Empty *Empty::operator&() const    //取址运算符(const)  
  12. {  
  13.   return this;  
  14. }  
  15. inline Empty::Empty(const Empty &rhs)           //拷贝构造函数  
  16. {  
  17.   //对类的非静态数据成员进行以"成员为单位"逐一拷贝构造  
  18.   //固定类型的对象拷贝构造是从源对象到目标对象的"逐位"拷贝  
  19. }  
  20.   
  21. inline Empty& Empty::operator=(const Empty &rhs) //赋值运算符  
  22. {  
  23.   //对类的非静态数据成员进行以"成员为单位"逐一赋值  
  24.   //固定类型的对象赋值是从源对象到目标对象的"逐位"赋值。  
  25. }  
         例如:m是类C中的一个类型为T的非静态成员变量,若C没有声明拷贝构造函数(赋值运算符), m将会通过T的拷贝构造函数(赋值运算符)被拷贝构造(赋值);该规则递归应用到m的数据成员,直到找到一个拷贝构造函数(赋值运算符)或固定类型(例如:int、double、指针等)为止。


三、总结

(1)上述运行结果依赖于编译器和64位、32位不同的系统。

(2)本博文只是总结一些C++特性,也有无法理解的地方,不足之处还请指出,在此先感谢!






































本文转自:

http://blog.csdn.net/taiyang1987912/article/details/43485569




非常抱歉,我在给出的代码中错误地提及了 `VirtualCamera` 类。事实上,SharpDX.MediaFoundation 库本身并没有提供直接创建虚拟摄像头的功能。要创建虚拟摄像头并将视频流推送到它,你可能需要使用第三方库或工具,例如虚拟摄像头驱动程序或框架。 一种常见的选择是使用 Dshow 系统库。你可以使用 DirectShow 库来创建虚拟摄像头,并使用 SharpDX.MediaFoundation 与 DirectShow 进行交互。以下是一个基本的示例代码,演示了如何将视频流推送到虚拟摄像头: ```csharp using System; using DirectShowLib; using SharpDX.MediaFoundation; class Program { static void Main() { // 加载虚拟摄像头驱动程序 var virtualCamera = LoadVirtualCameraDriver(); if (virtualCamera == null) { Console.WriteLine("无法加载虚拟摄像头驱动程序!"); return; } // 创建源视频文件的读取器 using (var sourceReader = CreateSourceReader("path/to/source/video.mp4")) { // 获取第一个视频流的格式 var mediaType = GetVideoMediaType(sourceReader, 0); // 将视频流推送到虚拟摄像头 PushVideoToVirtualCamera(sourceReader, virtualCamera, mediaType); Console.WriteLine("视频流已成功推送到虚拟摄像头!按任意键停止..."); Console.ReadKey(); } // 卸载虚拟摄像头驱动程序 UnloadVirtualCameraDriver(virtualCamera); } static IBaseFilter LoadVirtualCameraDriver() { // TODO: 加载虚拟摄像头驱动程序的代码 // 可以使用 DirectShowLib 库中的 FilterGraph 或其他相关类来加载虚拟摄像头驱动程序并获取其 IBaseFilter 对象 return null; } static void UnloadVirtualCameraDriver(IBaseFilter virtualCamera) { // TODO: 卸载虚拟摄像头驱动程序的代码 // 可以使用 DirectShowLib 库中的 FilterGraph 或其他相关类来卸载虚拟摄像头驱动程序 } static SourceReader CreateSourceReader(string videoFilePath) { var attributes = new MediaAttributes(); attributes.Set(CaptureDeviceAttributeKeys.SourceType, CaptureDeviceAttributeKeys.SourceTypeVideoCapture.Guid); var sourceReader = new SourceReader(videoFilePath, attributes); return sourceReader; } static MediaType GetVideoMediaType(SourceReader sourceReader, int streamIndex) { var mediaType = sourceReader.GetNativeMediaType(streamIndex, 0); return mediaType; } static void PushVideoToVirtualCamera(SourceReader sourceReader, IBaseFilter virtualCamera, MediaType mediaType) { var sample = new MediaSample(); // TODO: 将视频流推送到虚拟摄像头的代码 // 可以使用 DirectShowLib 库中的 FilterGraph 或其他相关类来将视频流推送到虚拟摄像头 } } ``` 注意,上述代码中的 `LoadVirtualCameraDriver` 和 `UnloadVirtualCameraDriver` 方法是示例代码,需要根据你使用的虚拟摄像头驱动程序进行实际实现。你可以使用 DirectShowLib 库中的 FilterGraph 类或其他相关类来加载和卸载虚拟摄像头驱动程序。 希望这次提供的代码能够帮助到你,如果你有任何进一步的问题随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值