[C++] 一文带你搞定 typedef 所有用法

typedef 用于将一种类型起别名,作用只有一个,少打字

但是,就是出这个原因,typedef 出现在各种标准库中,学习源码必备

[C++] typedef - 目录

1.简单的例子

1.1 Code

1.2 运行结果

2.使用方法

2.1 作用域

2.2 (常见)适用范围

2.2.1 基本数据类型

2.2.2 结构体(struct & typedef struct)

2.2.3 数组

2.2.4 函数

2.2.5 函数指针

2.2.6 类

2.2.7 类模板 & 结构体模板

2.2.8 函数模板

3. typedef 和 #define 的区别

3.1 #define

3.2 typedef

3.3 两者的联系

4. 相关C/C++文档&工具

4.1 文档

4.2 工具

4.3 Demo

Github

Gitee


1.简单的例子

1.1 Code

simple.cpp

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char** argv) {
   	
	typedef unsigned char uchar;
	uchar ch = 'a';
	cout << ch << endl;	

	typedef string S;
	S str = "Hello, world";
	cout << str << endl;

	return 0;
}

1.2 运行结果

 

2.使用方法

2.1 作用域

typedef 关键字有自己的作用范围,从声明关键字开始,到typedef所在的函数体\类结束

 typedef_scope.cpp

#include <iostream>
#define print cout << 

using namespace std;

void func_a () {

	typedef struct {
		long property_1;
		long property_2;
		int property_3;
	} llt, *p_llt;
	llt l1;
	p_llt(p_l1) = &l1; 
	p_l1->property_1 = p_l1->property_2 = p_l1->property_3 = 10;
	print p_l1->property_1 << p_l1->property_2 
			<< p_l1->property_3 << endl;

}

void func_b () {

	typedef struct { 
		double length; 
		double width; } Rec, * p_Rec;
	Rec r1;
	p_Rec p_r1 = &r1;
	p_r1->length = p_r1->width = 11;
	print r1.length << " " << r1.width << endl;

}

void func_c() {
	
	typedef long long int llt;
	llt num = 1e15;
	print num << endl;		

}

int main (int argc, char** argv) {
	
	func_a();
	func_b();
	func_c();

	return 0;

}

运行结果:

 

2.2 (常见)适用范围

 

2.2.1 基本数据类型

typedef unsigned long ulong, *p_ulong;

 

2.2.2 结构体(struct & typedef struct)

typedef struct {
		long property_1;
		long property_2;
		int property_3;
	} llt, *p_llt;

使用struct和 typedef struct 有区别吗?

我的理解是,写法不同,typedef struct 目前不能定义构造函数,但是其余使用方法没有区别

typedef_constructor.cpp

#include <iostream>

using namespace std;

struct Type_1 {

	int data;

	Type_1 () { 
		this->data = 100;
		cout << "Constructor of Type_1" << endl; 
	}

	void func1() { 
		cout << "data = " << this->data 
			<<" func1 in Type_1 calling" << endl;	
	}

};

typedef struct {
	
	int data = 200;
/*	
*	Type_2 () {
*		this->data = 200;
*		cout << "Constructor of Type_2" << endl;
*	}		
*
* Error: This struct has no type, actually, it is an anonymous struct 
*/
	
	void func2() {
		cout << "data = " << this->data << 
		" func2 in Type_2 calling" << endl;
	}

} Type_2;

int main (void) {

	Type_1 t1;
	t1.func1();	

	Type_2 t2;
	t2.func2();
	return 0;
}

输出结果:

diff_struct_typedef.cpp

#include <iostream>

using namespace std;

typedef struct { 
	double x; 
	double y; } Point, * p_Point;

struct Circle {
	Point centre;
	double radius;
};

int main (int argc, char** argv) {

	Point p1;
	Circle c1;
	p1.x = p1.y = 0;
	Circle* p_c1 = &c1;
	p_c1->centre = p1;
	p_c1->radius = 10;
	cout << "C1 : (" << c1.centre.x << ", " << c1.centre.y << ", "
		 << c1.radius << ")" << endl; 	

	return 0;

}

 运行结果:

 

2.2.3 数组

typedef int int_10[10];

typedef_arr.cpp 

#include <iostream>
using namespace std;

int main (int argc, char** argv) {
	typedef int int_10[10];
	int_10 new_arr;
	for (auto & ele : new_arr) {
		ele = 1;
	}
	for (auto & ele : new_arr) {
		cout << ele << " ";	
	}
	cout << endl;

	// Auto len detection
	typedef int auto_int[];
	auto_int arr1 = {1, 2, 3};
	auto_int arr2 = {1, 2};
	for (auto ele : arr1) {
		cout << ele << " ";
	}
	cout << endl;

	for (auto ele : arr2) {
		cout << ele << " ";
	}
	cout << endl;	

	return 0;

}

运行结果:

 

2.2.4 函数

C++中,不允许在函数的内部定义函数

typedef_func.cpp

#include <iostream>
#include <ctime>
#include <cstdlib> 

using namespace std;

typedef unsigned int uint;
typedef int func_type_0(int, int);
typedef double func_type_1(int, int);

class MyTools {
	private:
		MyTools (); 
	public:			
		static MyTools* get_instance(void);		
		func_type_0 rand_int; 
		// Define a function rand_int with function type
		// func_type_0
		
		func_type_0(ave_int);
		// Define a function ave_int with function type
		// func_type_1
		
};

MyTools :: MyTools () {
	srand(time(uint(NULL))); 
} 


MyTools* MyTools :: get_instance(void) {
	static MyTools instance;
	return & instance;
}

int MyTools :: rand_int(int min, int max) {
	return ((double)rand()) / RAND_MAX * (max - min) + min;
}

int MyTools :: ave_int(int a, int b) {
	return (a + b) / 2;
}

typedef struct {
	
/*	func_type_1 f1[4];
*
*   Error:
*   	Declearation f1 as array of functions
*	Hint: 
*		We can not create function arrays so far
*
*/

/*
*	func_type_1 f;
*   Warning:
*		f will not work coz we can not define it outside an 
*       anonymous struct
*		
*/

	func_type_1* p_f;
			
} Func_hook, *p_hook;

double my_add(int a, int b) {
	return a + b;
} 

double my_sub(int a, int b) {
	return a - b;
}

double my_mul(int a, int b) {
	return a * b;
}

double my_div(int a, int b) {
	return  double(a) / double(b);
}

Func_hook* init_cal (void) {
	p_hook cal = new(Func_hook);
/*
*	cal->f = *my_sub;
*   Error:
*		Syntax error, C++ has no such thing as function variables so far
*
*/
	cal->p_f = my_add;
	return cal;
}

int main (void) {
	MyTools * sing_ins = MyTools :: get_instance();
	p_hook h = init_cal();
	int num1 = sing_ins->rand_int(0, 255);
	int num2 = sing_ins->rand_int(0, 255);
	cout << num1 << " + " << num2
		<< " = " << (*(h->p_f))(num1, num2)  << endl;
	h->p_f = my_div;
	cout << num1 << " / " << num2 
		<< " = " << (*(h->p_f))(num1, num2) << endl;   
	delete h;
	return 0;
}

运行结果:

说明:

这里使用了“函数类型”的typedef定义

typedef int func_type_0(int, int);
typedef double func_type_1(int, int);

 定义了两个函数类型,func_type_0和func_type_1

func_type_0类型的函数满足,两个int型参数,一个int型返回值

func_type_1类型的函数满足,两个int型参数,一个double型返回值

 

上面的代码中注释掉的部分是报错的,测试发现:

1.虽然可以通过typedef定义一种函数类型例如func_type,但是不能用func_type funcs[10]这样去定义函数数组

2.typedef struct得到的struct没有名字,不能在其中定义构造函数

3.使用函数模板func_type定义的函数f不能对其进行赋值,即对于一个已经实现的函数g(既有声明也有定义),f=*g报错

def void func_type(void)
// ...
void g(void) { 
    // code
}
func_type f;

// f = *g; 
// Syntax Error

4.函数指针指向函数的时候,不需要对函数名进行取地址操作

函数名类似数组名,本身就是地址值,直接使用函数名对同类型函数指针赋值即可

 

2.2.5 函数指针

参考:函数指针

使用 typedef 定义函数指针与定义函数的唯一区别就是使用在函数名前面加一个‘*’

例如定义一个函数类型func_type,返回值arr_t* 类型,参数为void:

typedef arr_t* (func_type)(void); 

对应地可以定义一个函数指针类型p_func_type:

typedef arr_t* (*p_func_type)(void); 

 函数类型和函数指针类型的联系:

两者可以相互转换:

对于上面定义的func_type和p_func_type,两者之间存在关系:

// Define function type and func_pointer type
typedef arr_t* (func_type) (void);
typedef arr_t* (*p_func_type) (void);


// Create a function matching the function type
arr_t* example_func (void) {
    return NULL;
}

// Create a function pointer pointing to the function "example_func"
p_func_type new_func_pointer = example_func;

// Use function type to create the same type func_type pointer -> p_func 
// as p_func_type, And assign the same value (function address) to the p_func
func_type * p_func = new_func_pointer;

上面的例子说明了,可以使用函数类型创建与对应函数指针类型相同类型的函数指针

但是经过测试,只能对函数指针进行赋值以及覆盖性赋值,所以函数指针可以看成是一个变量,可以指向不同的函数

但是函数类型的只能用于定义新的函数,却不能对其进行赋值:

在上面的2.2.4中测试发现,C++没有函数类型变量这种东西:

f 是一个定义的函数类型,my_sub是函数名(就是指向这个函数的指针)

但是并不能通过对这个地址做“*”操作后将其赋值给函数类型变量cal->f

 

2.2.6 类

#include <iostream>

using namespace std;

class A_very_long_class_name {
	
	public:
	
		int data;
		void info(void) {
			cout << "data = " << 
			this->data  << endl;
		}

};

typedef A_very_long_class_name A;
 
int main(void) {
	A a;
	a.data = 10;
	a.info();	
	return 0;
}

输出结果:

 

2.2.7 类模板 & 结构体模板

参考:类模板 & 结构体模板

例如C++的标准库中有一个给已知的数据类型加上 const 限制的方法:参考:std :: add_const

实现方法:

template <class T>
struct add_const {
    typedef const T type;
};

使用:

#include <iostream>

using namespace std;


typedef std :: add_const<int> :: type cint;
typedef std :: add_const<unsigned char> :: type cuchar;

int main() {

	cint lt_num = 10086;
	cuchar lt_ch = '+';
	
	cout << lt_ch << lt_num << endl;

	return 0;
}

输出:

实现一个类似的,生成一对初始化一次后不能修改,只能读取的数据:

#include <iostream>

using namespace std;

template <class T, class Y>
struct const_pair {

	typedef const T type_0;
	typedef const Y type_1;
	
	type_0* p1;
	type_1* p2;
	
	const_pair (T t, Y y) {
		p1 = new type_0(t);
		p2 = new type_1(y);
	}
	
	~const_pair () {
		if (p1) delete p1;
		if (p2) delete p2;
	}
};

int main(void) {

	const_pair <int, double> nice_pair(10, 9.9);
	
	cout << *nice_pair.p1 << endl;
	cout << *nice_pair.p2 << endl;

/*	
*	*nice_pair.p1 = 100;
*	*nice_pair.p2 = 99;
*	
*	Error:
*		Can not change read-only data (const)
*
*/
	return 0;
}

输出:

typedef在模板类中的使用,见下面的2.2.8,和模板函数一起举例

 

2.2.8 函数模板

参考:函数模板

这个可以用OpenCV的源码来进行说明,顺便说明typedef在模板类中的应用

在OpenCV中有一个Mat_类,可以方便地实现对像素的访问

Mat_在实例化的时候,需要传入类型参数,比如:

Mat_<Vec3b> _I = I;

参考:Vec3b的解释

经过前面的学习,明显能够感受到Mat_类应该是有一个类型参数的模板类

Mat_类中有一个操作(i, j)可以直接访问对应的像素:cv :: Mat_ :: operator ()

此函数的声明和在类Mat_中,Mat_的声明和Mat类在同一个文件mat.hpp中

其路径是:opencv4/opencv/modules/core/include/opencv2/core/mat.hpp

找到如下两部分代码:

template<typename _Tp> class Mat_ : public Mat
{
public:
    typedef _Tp value_type;
    typedef typename DataType<_Tp>::channel_type channel_type;
    typedef MatIterator_<_Tp> iterator;
    typedef MatConstIterator_<_Tp> const_iterator;

    //! default constructor
    Mat_();
    //! equivalent to Mat(_rows, _cols, DataType<_Tp>::type)
    Mat_(int _rows, int _cols);

// more code ...
    //! returns reference to the specified element (2D case)
    _Tp& operator ()(int row, int col);

那么,typedef在模板类中的用法,以及在模板函数中的用法就很明确了,例如上面:

typedef _Tp value_type;

 就将传入的模板类型参数起了别名为value_type

但是有意思的是照理来说,在类Mat_ 进行了typedef _Tp value_type

但是最终在定义函数 _Tp& operator () (int, int) 的时候却还是偷懒使用

了_Tp& 而不是 value_type&,看来偷懒真的是人的天性,顶级的软件工程师(写opencv库的大牛)也不例外...

 

3. typedef 和 #define 的区别

 

3.1 #define

#define 是编译前的预处理器进行选择性替换的依据

例如上面代码中的

#define print cout << 

宏还可以用作选择性编译的控制开关:参考:宏在编译中的作用

 

3.2 typedef

给各种类型(基本类型,数组,函数,函数指针,类,模板...)起别名,用法见上

 

3.3 两者的联系

宏定义和typedef,两者常常搭配使用,例如在库文件中,如果有系统依赖

就会使用宏定义来控制选择合适的typedef进行编译

这样编译好之后,就可以给使用该库的人(无论他/她在什么平台工作)一个统一的使用接口

例如已知写好的库在ILP32和LP64下工作

那么下面的接口wchar_t在两个不同的系统下都占32位:

#ifdef _LP64
typedef int wchar_t;
#else
typedef long wchar_t;
#endif

 

参考: _LP64等的解释

 

4. 相关C/C++文档&工具

4.1 文档

http://unixwiz.net/techtips/reading-cdecl.html

4.2 工具

sudo apt install cdecl

4.3 Demo

Github

Gitee

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值