1.ifndef define endif

我们经常在c++的头文件中见到一堆#ifndef #define #endif这种标识。这些到底是用来干啥的?
在一个比较大的工程里,可能会出现一个头文件被多个文件同时include的情况。然后当这些文件编译链接成一个可执行文件的时候,会出现大量重复定义的错误。

比如我们打开stl库中vector源码,开头就有这么一个定义

#ifndef _LIBCPP_VECTOR
#define _LIBCPP_VECTOR
.......

然后文件最后定义

#endif  // _LIBCPP_VECTOR

ifndef,意为if not define。意思是当文件编译到该行,如果该文件还没被编译过,那么程序将define _LIBCPP_VECTOR,并执行后面的代码。反之将不会再次编译文件。

endif出现在程序的最后,与ifndef或ifdef配对出现,作为结束的标识符。

2.typedef定义类型别名

typedef,很容易就能明白他的作用是type define。我们可以看看他的几个常见用法。

比如我们在stl源码中,经常看到这种类似的代码

public:typedef _Allocator                               allocator_type;typedef allocator_traits<allocator_type>         __alloc_traits;typedef typename __alloc_traits::size_type       size_type;
protected:typedef _Tp                                      value_type;typedef value_type&                              reference;

上面的例子,就是为类别举个别名。比如将_Tp起个别名为value_type。这样做最大的好处就是可以非常简单明了的读懂变量的含义。

我们也可以自己举一个例子。

#include<iostream>
using namespace std;
typedef int Price;void func() {Price price = 10;cout<<"book's price is: "<<price<<endl;
}int main(int argc, char const *argv[])
{func();return 0;
}

这样在其他地方,我们就可以将Price代替int当做一种类型直接使用了,这样代码的可读性就得到了较大提高。

3.typedef定义平台类型

typedef定义平台类型也是我们在各种类库源码中常见的一种方式。

以size_t为例,_size_t.h头文件定义如下

#ifndef _SIZE_T
#define _SIZE_T
#include <machine/_types.h> /* __darwin_size_t */
typedef __darwin_size_t        size_t;
#endif  /* _SIZE_T */

可以看到size_t其实就是__darwin_size_t。

如果我们再查看__darwin_size_t

#if defined(__SIZE_TYPE__)
typedef __SIZE_TYPE__           __darwin_size_t;        /* sizeof() */
#else
typedef unsigned long           __darwin_size_t;        /* sizeof() */
#endif

上面这段代码告诉我们,如果定义了__SIZE_TYPE__类型,那么__darwin_size_t就是__SIZE_TYPE__。如果没有,就将unsigned long定义为__darwin_size_t。

宏定义就是简单的字符串替换。与定义宏相比,typedef是定义了一种类型的新别名,而不是单纯的字符串替换,所以他比宏要来的稳妥。

4.typedef struct

typedef还可以与struct配合使用,为struct定义别名。

typedef struct Teacher {string name;int age;Teacher(string tname, int tage): name(tname), age(tage) {}
}tea;void func() {tea t1("lili", 26);cout<<"name is: "<<t1.name<<", age is: "<<t1.age<<endl;
}int main(int argc, char const *argv[])
{func();return 0;
}

输出结果:

name is: lili, age is: 26

上面的代码为Teacher结构体定义了别名tea,后面就可以直接使用tea。
如果struct前面没有typedef关键字,那么tea将会是一个变量而不是别名。具体可以看下面的代码

struct Teacher {string name;int age;
}tea;void func() {tea.name = "lili";tea.age = 26;cout<<"name is: "<<tea.name<<", age is: "<<tea.age<<endl;
}int main(int argc, char const *argv[])
{func();return 0;
}

此时代码的输出为

name is: lili, age is: 26

应该可以看出两者的区别

typedef typename

我们还经常看到typedef typename连在一起的用法,比如我们在vector的源码中,能看到大段这种定义:

    typedef typename __base::__alloc_traits          __alloc_traits;typedef typename __base::reference               reference;typedef typename __base::const_reference         const_reference;typedef typename __base::size_type               size_type;typedef typename __base::difference_type         difference_type;typedef typename __base::pointer                 pointer;typedef typename __base::const_pointer           const_pointer;

上面为什么要加上typename的关键字?
主要是在类型实例化之前,编译器并不知道像__base::size_type 这种是什么东东,因为__base引用size_type,有三种可能情况:
1.size_type是__base的静态成员变量。
2.size_type是__base的静态函数。
3.size_type是__base的嵌套内部类。

我们通过typename关键字,就明确告诉编译器,size_type是第三种情况为嵌套内部类,而不是前面两种情况。

#ifndef #define #endif typedef typename相关推荐

  1. ifndef/define/endif——主要目的是防止头文件的重复包含和编译

    原文:http://www.jb51.net/article/100939.htm 原文:https://blog.csdn.net/abc5382334/article/details/180527 ...

  2. c:#ifndef, #define, #endif 作用

    #ifndef, #define, #endif 作用 #ifndef 它是if not define 的简写,是宏定义的一种,实际上确切的说,这应该是预处理功能三种(宏定义.文件包含.条件编译)中的 ...

  3. c/c++头文件中#ifndef/#define/#endif的用法

    想必很多人都看过"头文件中用到的 #ifndef/#define/#endif 来防止该头文件被重复引用".但是是否能理解"被重复引用"是什么意思?头文件被重复 ...

  4. [Windows编程] #pragma once 和#ifndef ... #define ... #endif 比较

    C++中防止头文件被多次include 的常见方式有: 1) 用#ifndef ...  #define ... #endif  宏 #ifndef __MYHEADER_H__ #define __ ...

  5. C语言头文件为什么要加#ifndef #define #endif(防止头文件重复包含)

    当你用VC的菜单新增一个类,你会发现自动生成的代码总是类似下面的样子: #if !defined(AFX_XXXX__INCLUDED_)#define AFX_XXXX__INCLUDED_具体代码 ...

  6. C++中#ifndef/#define/#endif使用详解

    想必很多人都看过"头文件中的 #ifndef/#define/#endif 防止该头文件被重复引用".但是是否能理解"被重复引用"是什么意思?是不能在不同的两个 ...

  7. #ifndef/#define/#endif

    #ifndef/#define/#endif 头文件中的 #ifndef/#define/#endif 防止该头文件被重复引用 "被重复引用"是指一个头文件在同一个cpp文件中被i ...

  8. 【转载】#pragma once与#ifndef #define #endif的区别

    一.相同点         两者的共同点都是为了避免同一个文件被 include 多次,但是 #ifndef #define #endif 不只有这个作用.  在能够支持这两种方式的编译器上,二者并没 ...

  9. #ifndef.#define, #endif 的用法

    文件中的#ifndef.#define, #endif 很关键,是为了避免多重包含,比如如果两个C文件同时包含同一头文件,那么就会出现问题,所以使用这种方法可以有效避免这种情况. 一般用法: 以add ...

  10. 每日一题(12)—— .h头文件中ifndef/define/endif的作用

     .h头文件中ifndef/define/endif的作用? 分析: 防止头文件被重复包含. #ifndef _TEST_H_ #define _TEST_H_/* test.h */#endif / ...

最新文章

  1. CI框架 -- 附属类
  2. 英伟达验证图片加载不出来_让大卫雕塑跳舞、蒙娜丽莎说话,英伟达视频合成有如此多「骚操作」...
  3. linux systemd服务,systemd服务管理
  4. ML之sklearn:sklearn.metrics中常用的函数参数(比如confusion_matrix等 )解释及其用法说明之详细攻略
  5. java contains 通配符_java删除文件支持通配符
  6. 在Vs.net中集成 NDoc生成的 Html Help 2帮助文档
  7. 5_1 大理石在哪儿(UVa10474)排序与查找
  8. MSSQLServer基础07(事务,存储过程,分页的存储过程,触发器)
  9. Linux下查看CPU信息、机器型号等硬件信息命令
  10. 【转载】分层开发思想与小笼包
  11. 诺基亚在日本测试5G网络 网速可达256MB/s
  12. create user 'root'@'localhost' identified by 。。。
  13. Typecho中的gravatar头像无法加载
  14. 犀牛插件开发-插件兼容性-Rhino插件-什么是Rhino插件
  15. 004--MySql数据库的淘宝商城数据库设计
  16. mac android studio keymap,Android Studio keymap for Mac
  17. day16 Java 集合
  18. Alphafold2蛋白质三维结构预测AI工作站配置
  19. 马云 996 一文的诡辩与话术:大家是怎么被洗脑还帮人数钱的
  20. java ftp上传文件 linux_linux下用java实现ftp上传、下载文件

热门文章

  1. 如何将倾城时光录制成MP3格式
  2. supervisor 管理
  3. Citrix为什么要兼容第三方服务器虚拟化平台
  4. 项目开发中遇到的问题,原因,解决思路
  5. OCS2007视频会议客户端的部署与应用
  6. git --amend 使用和撤销
  7. wait方法为什么要放在循环里
  8. 带宽与虚拟桌面的考虑
  9. Ionic3学习笔记(二)主题化
  10. 五方面入手精选数据库审计产品