#ifndef #define #endif typedef typename
Posted bitcarmanlee
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#ifndef #define #endif typedef typename相关的知识,希望对你有一定的参考价值。
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的主要内容,如果未能解决你的问题,请参考以下文章
浅谈c/c++头文件中#ifndef/#define/#endif的用法