`
yidongkaifa
  • 浏览: 4067062 次
文章分类
社区版块
存档分类
最新评论

C++中的void类型

 
阅读更多
Technorati 标签: void,指针

1.1. void类型

void类型其实是一种用于语法性的类型,而不是数据类型,主要用于作为函数的参数或返回值,或者定义void指针,表示一种未知类型。

1.1.1. 作为函数参数与返回值

void func( void );

void func( );

例如上面两例,其实两种声明方式是等效的,在C++中如果参数列表为空,默认的参数类型即为void,但建议没有参数时使用void以提高程序的可读性。

因为C++在定义函数时不允许返回值类型为空,在C++98之前,是允许定义函数时不定义返回值的,默认的返回值是int类型。其实默认int类型并不是好事,如果函数有返回值在函数返回时是需要消耗CPU传递返回值的,也或许也是C++98标准将默认返回值类型改为void的原因。

因为C++不允许默认返回值,所以当函数不需要返回值是,需要将返回值类型声明为int类型。当调用返回值类型为void类型的函数时,在工程上有很多实际代码在前面加上(void)类型转换,以提高代码的可读性。如调用上面定义的 func函数。

(void)func( );

从另一个角度讲,这样严谨的方式是可以提高软件的健壮性的,调用函数时可以明确地看出是没有返回值的,如果调用一个返回值不是int类型的函数时最好判断其返回值,以检查函数调用是否成功,如:

#include <cstdio></cstdio>

char buff[5];

func( );

snprintf(buff, sizeof(buff), “%d”, “10240”);

显然这段代码是有问题的,当然func没有返回值,这样调用是没有问题,但snprintf的调用会有问题因为缓冲区有可能太小而不能容纳结果字符串,上面的代码就有这个问题。假设我们不知道snprintf有没有返回值,可能这个BUG我们不会发现,直到有一天出现了我们不期望的结果。如果我们严格要求调用每个函数时必须判断函数的返回值,按照以下面的代码编码,就不会出给我们的程序造成隐患。

#include <cstdio></cstdio>

#include <stdexcept></stdexcept>

char buff[5];

(void)func( );

if( sizeof(buff)

buff[sizeof(buff) - 1] = '/0';

throw std::overflow_error("buff overflow");

}

1.1.2. void指针

void* pv = NULL;

string str = "string";

int i = 1;

pv = &str;

pv = &i;

int *pi = (int*)pv;

string* ps = (string*)pv;

如上面的示例所示,void指针表示未知类型的指针,可以将任意类型的指针直接赋值给void指针,好比是C#、Java中的object引用,可以把任意类型的对象赋值给它。但把void类型赋值给特定类型的指针时,就需要进行强制转换,因为C++为类型语言,尽可能保证类型安全,如果使用了强制类型转换,编译器就认为程序员知道他(她)在干什么,程序也应该负起这样做的责任。

值得注意的是,函数指针与类成员的指针不能赋值给void*类型变量。

void*在C语言中一般用于动态内存的操作,因为malloc和calloc返回的类型都是void*类型。在W3C的协议库libwww里,大量使用了void*类型,如果使用C++的继承特性的话,应该会使代码可读性更好。而在C++中则可以使用new返回特定类型指针,更不容易出现问题,所以void*的作用显得更弱了。

void*在C++中的主要作用就是作为函数指针的返回值[C++ Programming Language],例如:

void* my_alloc(size_t size);

void* 还用于一些底层的操作,例如我们有两个类UdpSocket和TcpSocket,在我们一个传输类中需要支持两种协议,提供统一的接口,但UdpSocket和TcpSocket之间没有继承关系,无法使用共同的基类指针,而只能使用void*指针,代码如[??]。

class UdpSocket{};

class TcpSocket{};

class Transfer

{

public:

enum Protocol { UDP, TCP };

Transfer(Protocol prot) : _prot(prot)

{

if( _prot == UDP)

_sock = new UdpSocket( );

else if( _prot == TCP )

_sock = new TcpSocket( );

else

throw std::invalid_argument("prot");

}

~Transfer( void )

{

if(_prot == UDP)

delete (UdpSocket*)_sock;

else

delete (TcpSocket*)_sock;

_sock = NULL;

}

private:

void* _sock;

Protocol _prot;

};

分享到:
评论

相关推荐

    C++数据类型及取值范围

    C++数据类型及取值范围 1.基本数据类型: ①字符类型:char(字符型) 例:‘A’,’b’ ②整数类型:int(整型) 例:4563, 234, 885634 ③浮点类型:float(单精度型)、double(双精度型) 例:3.1456 , 0.9e12 ④空值...

    void 指针详解(用法、注意事项等等 )

    许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误。本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧。

    在c++中实现属性

    在C++中实现属性 本文译自http://www.codeguru.com/cpp_mfc/Property.html的Implementing a Property in C++ 以下是译文 本文由Emad Barsoum投稿。 开发测试环境:Visual C++ 7.0, Windows XP sp1, Windows 2000...

    C++ 中文 代码即为注释 注释即为代码

    C++中文头文件 中文关键字定义 还有快捷函数库 例如 全套进程提权() 函数 即可获取所有令牌权限(共35个令牌) 还有基本的文件流 void 写入文件(路径,字符,类型) string 读取文件(路径)

    C和C++编程语言数据类型

    c语言和c++的几种基本语言类型,C语言包含5个基本数据类型: void, integer, float, double, 和 char.

    面向C++11的轻量级同步事件框架

    与C#和Java等托管语言不同,C++是静态类型的,不支持反射或匿名委托,这使得事件系统稍微困难一些。本项目试图创建一个简单、轻量级的事件框架,可以轻松地适应任何C++11项目。唯一的要求是支持C++11和访问标准C++库...

    C++ 中const 类型限定符不兼容问题

    今天在写程序的时候,出现了一个错误 “对象包含与成员函数不兼容的类型限定符”,从... 您可能感兴趣的文章:C++中const用法小结C和C++ const的声明差异C++ 中const和复合类型C++中的const和constexpr详解C++编程中的co

    C# 调用C++ DLL的类型转换

    //C#调用C++的DLL搜集整理的所有数据类型转换方式,可能会有重复或者多种方案,自己多测试 //c++:HANDLE(void *) —- c#:System.IntPtr //c++:Byte(unsigned char) —- c#:System.Byte //c++:SHORT(short) —- c#...

    新手学习C++入门资料

    C++中还包括wchar_t数据类型,wchar_t也是字符类型,但是是那些宽度超过8位的数据类型。许多外文字符集所含的数目超过256个,char字符类型无法完全囊括。wchar_t数据类型一般为16位。 标准C++的iostream类库中包括...

    C++语言中类、继承、多态等的用法?

    通过C++语言中的继承机制,一个新类既可以共享另一个类的操作和数据,也可以在新类中定义已有类中没有的成员。 class CBase { public: void FuncA(void); void FuncB(void); }; //派生类 class CDerive :...

    C++中BOOL和bool的区别

     二:bool是标准C++数据类型,可取值true和false。单独占一个字节,如果数个bool对象列在一起,可能会各占一个bit,这取决于编译器。  BOOL是微软定义的typedef int BOOL。与bool不同,它是一个三值逻辑,TRUE/...

    C++基本概念 (面试、复习)

    在C++中标识符区分大小写,另外标识符不能和C++中的关键字相同,也不能和函数同名。 4.声明  将一个标识符引入一个作用域,此标识符必须指明类型,如果同时指定了它所代表的实体,则声明也是定义。

    void指针小结

    许多初学者对C/C++诧言中的void及void指针类型丌甚理解,因此在使用上出现了一些错诨。本文将对void关键字的深刻含义迚行解说,并详述void及void指针类型的使用方法不技巧。

    c++一些基本的处理函数

    void __stdcall bcdtohex(BYTE b,BYTE *buf); bool __stdcall hextostring(unsigned char *inbuf,int inlen,unsigned char * outbuf); bool __stdcall stringtohex(unsigned char *inbuf,int inlen,unsigned char * ...

    C++动态数组类模板

    动态数组类模板Array C++ //数组类模板声明 ... //T类型指针,存放动态分配的数组内存首地址 int size; void Error(ErrorType error, int badIndex = 0)const; //错误处理函数 }; ................

    int main和int main(void)区别

    在c++中int main()和int main(void...在c语言中main()省略返回类型也就相当说明返回类型为int型,不过这种用法在c++中逐渐被淘汰。虽然Void main()在很多系统都适用,但他毕竟不是标准的,所以应该避免这种用法

    传智播客_C++基础课程讲义_v1.0.7

    4.6 C++中所有的变量和函数都必须有类型 6 4.7新增Bool类型关键字 6 4.8三目运算符功能增强 6 5 C/C++中的const 6 1 const基础知识(用法、含义、好处) 6 2 C中“冒牌货” 6 3 const和#define相同之处 6 4 const和#...

    c++显式类型转换示例详解

    标准C++包含一个显式的转换语法: static_cast:用于“良性”和“适度...static_cast:用于所有明确定义的转换,包括void*的强制转换、隐式类型转换、类层次的静态定位。 1. 数据类型由小到大的转换,比如int转换为long

    Absolute C++中文版(原书第2版)-完美的C++教程,文档中还包含英文版

    3.2.6 void函数中的return语句 77 3.2.7 前提条件和执行结果 78 3.2.8 main函数 79 3.2.9 递归函数 79 3.3 作用域规则 80 3.3.1 局部变量 80 3.3.2 过程抽象 82 3.3.3 全局常量与全局变量 83 3.3.4 语句块 ...

    专业的log类(C++)类

    virtual void Write(const char *str, const int &grade;); public: Log(); ~Log(); virtual std::string LogTime(); void WriteLog(const char *str, const int &grade; = 0); void WriteLog(const std::...

Global site tag (gtag.js) - Google Analytics