typedef 用于将一种类型起别名,作用只有一个,少打字
但是,就是出这个原因,typedef 出现在各种标准库中,学习源码必备
[C++] typedef - 目录
2.2.2 结构体(struct & typedef struct)
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;
经过前面的学习,明显能够感受到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
4. 相关C/C++文档&工具
4.1 文档
http://unixwiz.net/techtips/reading-cdecl.html
4.2 工具
sudo apt install cdecl