C++元编程语言初步入门详解

  目录

  模板

  由于模板元编程需要以面向对象为基础,所以如有疑问之处可以先补充一点C++面向对象的知识:

  C++面向对象这一篇就够了

  泛型初步

  由于C++是静态强类型语言,所以变量一经创建,则类型不得更改。如果我们希望创建一种应用广泛地复数类型,那么相应地需要基于、、这些基础类型逐一创建,十分麻烦。泛型编程便是为了简化这一过程而生。

  能够容纳不同数据类型作为成员的类被成为模板类,其基本方法为在类声明的上面加上一行模板声明代码

  template,下一行为class myClass,其调用过程为myClass m。

  列举案例如下

  #include

  using namespace std;

  template

  struct Abstract{

  C real; //real为C类型

  C im;

  Abstract(C inReal, C inIm){

  real = inReal;

  im = inIm;

  }

  void printVal(){

  cout<<"Abstract:"<

  };

  Abstract& multi(Abstract val){

  C temp = real*val.real - im*val.im;

  im = real*val.real + im*val.im;

  real = temp;

  return *this;

  };

  };

  int main(){

  Abstract fTemp{1,2};//C类型为float

  fTemp.multi(fTemp);

  fTemp.printVal();

  system("pause");

  return 0;

  }

  函数模板

  当然,上述并不能实现两个不同类型的之间的相乘,所以可以将函数改为

  template

  Abstract& multi(Abstract val){

  C temp = real*val.real - im*val.im;

  im = real*val.real + im*val.im;

  real = temp;

  return *this;

  }

  这样就能够实现如下功能。

  int main(){

  Abstract fTemp{1,2};

  Abstract iTemp{1,2};

  fTemp.multi(iTemp);

  fTemp.printVal();

  getReal(fTemp);

  system("pause");

  return 0;

  }

  友元

  模板类具备一部分普通类的性质,比如struct和class的区别,public、protected、private的性质,以及友元等。模板的声明特性也可以应用在函数中,例如

  #include

  using namespace std;

  template

  class Abstract{

  C real;

  C im;

  public:

  Abstract(C inReal, C inIm){

  real = inReal;

  im = inIm;

  }

  void printVal(){

  cout<<"Abstract:"<

  };

  Abstract& multi(Abstract val){

  C temp = real*val.real - im*val.im;

  im = real*val.real + im*val.im;

  real = temp;

  return *this;

  }

  template friend void getReal(Abstract num); //声明友元

  };

  template

  void getReal(Abstract num){

  cout<

  }

  int main(){

  Abstract fTemp{1,2};

  fTemp.multi(fTemp);

  fTemp.printVal();

  getReal(fTemp);

  system("pause");

  return 0;

  }

  需要注意的一点是,在模板类中声明友元,其前缀中的类型标识不得与已有的类型标识重复,否则编译无法通过。

  由于函数模板可以针对不同的数据类型进行求解操作,是对函数或者方法实例的抽象,所以又被称为算法。

  模板参数

  如果将模板理解为一种类型声明的函数,那么模板也应该具备一些函数具备的功能。首先其模板参数中可以包含实际类型参数,例如

  template

  class Test{}

  其调用时可以写为

  Test pixel;

  模板同样支持默认参数,即可以实现如下形式

  template

  class Test{}

  Test pixle;

  除了数据类型、值之外,模板本身也可以作为模板参数,例如下面的形式是合法的。

  template class C>

  struct Test{

  C* val;

  Test(C* inVal){

  val = inVal;

  }

  };

  int main(){

  Abstract fTemp{1,2};

  Test test(&fTemp);

  test.val->printVal();

  system("pause");

  return 0;

  }

  其结果为

  PS E:Codecpp> g++ .generic.cpp

  PS E:Codecpp> .a.exe

  Abstract:1+2i

  请按任意键继续. . .

  需要注意的一点是,在模板类中定义的模板类,需要进行实例化,否则会出现错误,所以在中,以指针形式创建了模板类。

  类型函数

  以数据类型为输入或输出的函数即为类型函数,在C语言中,便是一种类型函数,其输入为数据类型,输出为数据类型所需要的内存空间。

  在C++11中,可以实现数据类型赋予的功能,其使用方法与相似

  template

  struct Test{

  using type = T;

  }

  元编程的基本概念

  元编程是泛型编程的一个超集,两者的本质均是针对不同数据类型的算法,后者则更关注传入参数的广泛性。如果将元编程分为四个层次

  那么泛型编程可以作为第一类元编程,或者说更加关注的是参数的传入传出过程,而元编程则更关注不同数据类型的选择过程。

  例如,我们可以实现一个最多包含三个元素的元组,其思路为,三元元素可以看成是一个二元元组与一个参数的组合;二元元组可以看成是一元元组与参数的组合;一元元组则是一个基本数据类型的变量。在这个元组的实现过程中,除了赋值过程实现泛型之外,也需要判断当前所实现的元组元素个数,如果其初始化参量为3个时,需要递归式地创建变量,直到赋值参数为1个。则其实现如下

  class Nil{};

  //主模板

  template

  struct Tuple : Tuple{

  T1 x;

  using Base = Tuple; //三元元组以二元元组为基础

  //返回值为Tuple指针类型的base()函数

  //static_cast将this转化为Base*类型

  Base* base(){return static_cast(this);}

  const Base* base() const {return static_cast(this);}

  //构造函数继承二元元组,在构造本类中x的同时,构造基类Tuple

  Tuple(const T1& t1, const T2& t2, const T3& t3)

  :Base{t2,t3},x{t1}{}

  };

  template

  struct Tuple{

  T1 x;

  };

  template

  struct Tuple : Tuple{

  T1 x;

  using Base = Tuple;

  Base* base(){return static_cast(this);}

  const Base* base() const {return static_cast(this);}

  Tuple(const T1& t1,const T2& t2):Base{t2}, x{t1}{}

  };

  template

  void print_elements(ostream& os, const Tuple& t){

  os<

  print_elements(os,*t.base());

  }

  template

  void print_elements(ostream& os, const Tuple& t){

  os<

  print_elements(os,*t.base());

  }

  template

  void print_elements(ostream& os, const Tuple& t){

  os<

  }

  //运算符重载

  template

  ostream& operator<<(ostream& os, const Tuple& t){

  os<<"{";

  print_elements(os,t);

  os<<"}";

  return os;

  }

  int main(){

  Tuple x{1,2.5,'a'};

  cout<

  system("pause");

  return 0;

  }

  其输出结果为

  PS E:Codecpp> g++ .generic.cpp

  PS E:Codecpp> .a.exe

  {1,2.5,a}

  可变参数模板

  上述实现过程非常繁琐,而且限制了元组中的元素个数,如果标准库中用上述的书写风格,那么标准库除了这个元组之外也写不了其他的东西了。好在C++模板提供了可变参数的功能,例如,我们可以先将打印模板函数写为

  //typename... T 代表可变参数

  template

  void print_elements(ostream& os, const Tuple& t){

  os<

  print_elements(os,*t.base());

  }

  template

  void print_elements(ostream& os, const Tuple& t){

  os<

  }

  template

  ostream& operator<<(ostream& os, const Tuple& t){

  os<<"{";

  print_elements(os,t);

  os<<"}";

  return os;

  }

  其输出结果为

  PS E:Codecpp> g++ .generic.cpp

  PS E:Codecpp> .a.exe

  {1,2.5,a}

  请按任意键继续. . .

  然后将也做相同的更改

  template

  struct Tuple : Tuple{

  T1 x;

  using Base = Tuple; //N+1元元组以N元元组为基

  Base* base(){return static_cast(this);}

  const Base* base() const {return static_cast(this);}

  //注意T&...的书写格式

  Tuple(const T1& t1, const T&... t):Base{t...},x{t1}{}

  };

  template

  struct Tuple{

  T x;

  };

  /*

  print模板

  */

  int main(){

  Tuple tt("hello",1.5,1,'a');

  cout<

  system("pause");

  return 0;

  }

  其输出结果为

  PS E:Codecpp> g++ .generic.cpp

  PS E:Codecpp> .a.exe

  {hello,1.5,1,a}

  以上就是C++元编程语言初步入门详解的详细内容,更多关于C++元编程语言初步的资料请关注脚本之家其它相关文章!

  您可能感兴趣的文章: