C/C++ typedef
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;
return0; }
运行结果:
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
————————————————
版权声明:本文为CSDN博主「kikook」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chenhanxuan1999/article/details/99020715