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

char buff[5];

func( );

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

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

#include

#include

char buff[5];

(void)func( );

if( sizeof(buff) <= snprintf(buff, sizeof(buff), "%d", 10240) ){

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++中的void类型的更多相关文章

  1. Swift中的Void类型与空元祖表达式

    可能有不少Swift开发者会忽略这么一个细节:在Swift中,Void类型其实是一个别名类型,而其真正的类型为(),即一个空元祖(empty tuple)! 这种语言特性给Swift带来了一些比较方便 ...

  2. 关于void*类型的用法(相当于OC中的id类型)

    关于void*类型的用法(相当于OC中的id类型) 1.C++语言在对于void* 类型的使用很特别,因为void* 可以间接引用任何其他数据类型的指针,比如int*.float*甚至抽象数据类型的指 ...

  3. 向mysql中插入Date类型的数据

    先看数据库表的定义 date字段为sql.date类型.我要向其中插入指定的日期和当前日期. 一.插入当前日期 思路:先获取当前系统,在将当前系统时间转换成sql类型的时间,然后插入数据库.代码如下 ...

  4. 在文件夹中 的指定类型文件中 查找字符串(CodeBlocks+GCC编译,控制台程序,仅能在Windows上运行)

    说明: 程序使用 io.h 中的 _findfirst 和 _findnext 函数遍历文件夹,故而程序只能在 Windows 下使用. 程序遍历当前文件夹,对其中的文件夹执行递归遍历.同时检查遍历到 ...

  5. Java中的void

    转:关于void 学过java的人都知道void的意思是空,是java中的关键字.最初在知道void的时候是public static void main(String[]args){},我记得当初接 ...

  6. EffectiveJava——请不要在代码中使用原生态类型

    先看一个栗子,看看能不能找出来里面的错误: /** * 请不要在新代码中使用原生态类型 * @author weishiyao * */ public class Test { public stat ...

  7. JavaScriptSerializer 中的匿名类型 转json

    二:JavaScriptSerializer 中的匿名类型 这个类型我想大家都清楚,不过性能更高的方式应该是用JsonConvert吧,但这个不是本篇讨论的话题,我们重点来看看匿名类型的Json序列化 ...

  8. zk框架中利用map类型传值来创建window,并且传值

    @Command @NotifyChange("accList") public void clear(@BindingParam("id") String a ...

  9. .NET中的Timer类型用法详解

    这篇文章主要介绍了.NET中的Timer类型用法,较为详细的分析了Timer类型在各种环境下的用法,需要的朋友可以参考下   在.NET FrameWork中有多个Timer,那么怎么根据实际情况进行 ...

随机推荐

  1. CSU-1985 驱R符

    CSU-1985 驱R符 Description 阴阳师中有三中稀有度的式神R,SR,SSR,其中R的稀有度最低,每次抽符,会随机得到一种式神,然而子浩君对R式神已经深恶痛绝. 某天,子浩君突然发现, ...

  2. 双网卡只有一个能ping通的解决办法

    来源:http://blog.csdn.net/centerpoint/article/details/38542719 Linux默认启用了反向路由检查 如果2个网卡在一个Lan里面,那么服务器可能 ...

  3. mojoportal中使用jquey的插件

    以前在mojo中使用jquery的插件,都是把插件的文件内容直接写到了相关的模块中,这样的问题是不整洁,一大串代码. 如果直接在layout.master中引入插件文件,或者在自定义模块中引入插件文件 ...

  4. maven学习(二)——手动创建maven项目

    一.Maven的简单使用 1.Maven项目的目录约定 MavenProjectRoot(项目根目录)   |----src   |     |----main   |     |         | ...

  5. 【转】Unity3d实现物体围绕某一点进行旋转

    1,让一个物体围绕某一点旋转,有几种方法?分别是什么? 答:在这个点处放一个空物体B,则问题变为A绕着B旋转, 方法1:B不动,A挂脚本实现transform的RotateAround(vector3 ...

  6. 解决云服务器ECS,windows server 2012不能安装SQL Server 2012,不能安装.NET Fromework 3.5

    在云服务器上安装SQL Server 2012 时出现“启用windows功能NetFx3时出错”的问题:NetFx3指的是.NET Framework 3.5,SQL Server 2012数据库系 ...

  7. sql server 韩文查询匹配失败

    在SQL Server 中查询韩文信息时,没有匹配到对应的信息,检查程序后发现字段类型是nvarchar类型的没有问题, 打开存储过程后找到问题了:原来是拼接后的查询语句存储在一个varchar变量中 ...

  8. [SDOI2015][bzoj3994] 约数个数和 [莫比乌斯反演]

    题面: 传送门 思路: 首先,我们需要证明一个结论:d(i*j)等于sigma(gcd(x,y)==1),其中x为i的约数,y为j的约数 对于nm的每一个质因子pi分别考虑,设n = pi^ai + ...

  9. BZOJ3884 上帝与集合的正确用法 【欧拉定理】

    题目 对于100%的数据,T<=1000,p<=10^7 题解 来捉这道神题 欧拉定理的一般形式: \[a^{m} \equiv a^{m \mod \varphi(p) + [m \ge ...

  10. 核苷酸(evolution)

    核苷酸(evolution) 题目描述 生物课是帕特里克最讨厌的课程,没有之一. 相比做一些无聊而又无趣的遗传题,他更喜欢其他所有的科目. 包括英语. 但是今天不同.他被一个关于RNA感染DNA的题目 ...