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

posted @ 2021-08-30 10:57  默行于世  阅读(110)  评论(0编辑  收藏  举报