C语言的宏与C++里面的模板的区别:1、概念不同;2、语法不同;3、应用不同。概念不同是指C语言的宏定义是C语言本身的组成部分且不能直接对它们进行编译,而C++里面的模板允许程序员定义一种适用于不同类型的对象的行为。
一、C语言的宏与C++里面的模板的区别
1、概念不同
C语言的宏:C语言中的宏定义也叫做预处理命令,预处理命令是C语言本身的组成部分,不能直接对它们进行编译。
C++里的模板:C++里面的模板允许程序员定义一种适用于不同类型的对象的行为,模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。模板是创建泛型类或函数的蓝图或公式。库容器,比如迭代器和算法,都是泛型编程的例子,它们都使用了模板的概念。
2、语法不同
C语言的宏:在 C 语言中,可以采用命令 #define 来定义宏。该命令允许把一个名称指定成任何所需的文本,例如一个常量值或者一条语句。在定义了宏之后,无论宏名称出现在源代码的何处,预处理器都会把它用定义时指定的文本替换掉。关于宏的一个常见应用就是,用它定义数值常量的名称:
define #ARRAY_SIZE 100
double data[ARRAY_SIZE];
这两行代码为值 100 定义了一个宏名称 ARRAY_SIZE,并且在数组 data 的定义中使用了该宏。惯例将宏名称每个字母采用大写,这有助于区分宏与一般的变量。上述简单的示例也展示了宏是怎样让 C 程序更有弹性的。
C++里的模板:模板函数定义的一般形式如下所示:
template <typename type> ret-type func-name(parameter list) { // 函数的主体 }
3、应用不同
C语言的宏:以表格形式输出一个函数的值,该程序使用了嵌套的宏。
#include <stdio.h>
#include <math.h> // 函数cos()和exp()的原型
#define PI 3.141593
#define STEP (PI/8)
#define AMPLITUDE 1.0
#define ATTENUATION 0.1 // 声波传播的衰减指数
#define DF(x) exp(-ATTENUATION*(x))
#define FUNC(x) (DF(x) * AMPLITUDE * cos(x)) // 震动衰减
// 针对函数输出:
#define STR(s) #s
#define XSTR(s) STR(s) // 将宏s展开,然后字符串化
int main()
{
double x = 0.0;
printf( "\nFUNC(x) = %s\n", XSTR(FUNC(x)) ); // 输出该函数
printf("\n %10s %25s\n", "x", STR(y = FUNC(x)) ); // 表格的标题
printf("-----------------------------------------\n");
for ( ; x < 2*PI + STEP/2; x += STEP )
printf( "%15f %20f\n", x, FUNC(x) );
return 0;
}
C++里的模板:返回两个数最大的值。
#include <iostream>
#include <string>
using namespace std;
template <typename T>
inline T const& Max (T const& a, T const& b)
{
return a < b ? b:a;
}
int main ()
{
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
string s1 = "Hello";
string s2 = "World";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;
return 0;
}
二、使用#define定义宏函数
预处理器对宏指定的文本进行简单替换,因此可以使用编写简单的函数。宏函数通常用于执行非常简单的计算,相比于常规函数调用,宏函数的优点是:
- 在编译前就地展开
- 改善代码的性能
- 无需考虑数据类型
宏是简单的替换,对于宏函数一定要使用括号保证替换后的功能逻辑正确,这是使用宏函数中经常犯错误的点。正是宏不进行类型检查,所以使用宏函数可以作用于不同的变量类型。宏函数不像常规函数那样在函数调用时需要创建调用栈、传递参数等,这些开销占用CPU的时间通常比常规函数的执行时间还多。所以,对于简单的函数,通常可以使用宏函数进行。但是宏不支持任何形式的类型安全,而且复杂的宏调试起来不方便。如果比那些独立于类型的泛型函数,又要保证类型安全,可使用模板函数,而不是宏函数,如要改善性能,可以定义为内联函数,使用关键字inline,这样就完全覆盖了宏函数的优势。
三、C++模板的非类型形参
- 模板的非类型形参也就是内置类型形参,如template class B{};其中int a就是非类型的模板形参。
- 非类型形参在模板定义的内部是常量值,也就是说非类型形参在模板的内部是常量。
- 非类型模板的形参只能是整型,指针和引用,像double,String, String **这样的类型是不允许的。但是double &,double *,对象的引用或指针是正确的。
- 调用非类型模板形参的实参必须是一个常量表达式,即他必须能在编译时计算出结果。
- 任何局部对象,局部变量,局部对象的地址,局部变量的地址都不是一个常量表达式,都不能用作非类型模板形参的实参。全局指针类型,全局变量,全局对象也不是一个常量表达式,不能用作非类型模板形参的实参。
- 全局变量的地址或引用,全局对象的地址或引用const类型变量是常量表达式,可以用作非类型模板形参的实参。
- sizeof表达式的结果是一个常量表达式,也能用作非类型模板形参的实参。
- 当模板的形参是整型时调用该模板时的实参必须是整型的,且在编译期间是常量,比如template class A{};如果有int b,这时A m;将出错,因为b不是常量,如果const int b,这时A m;就是正确的,因为这时b是常量。
- 非类型形参一般不应用于函数模板中,比如有函数模板template void h(T b){},若使用h(2)调用会出现无法为非类型形参a推演出参数的错误,对这种模板函数可以用显示模板实参来解决,如用h(2)这样就把非类型形参a设置为整数3。
- 非类型模板形参的形参和实参间所允许的转换。
延伸阅读
模板声明的类型
模板声明可以是:
- 函数的声明或定义
- 类的声明或定义
- 类模板的成员函数或成员类的声明或定义
- 类模板的静态数据成员的定义
- 嵌套在类模板中的类的静态数据成员定义
- 类或类模板的成员模板的定义
文章标题:C语言的宏与C++里面的模板有什么区别,发布者:Z, ZLW,转载请注明出处:https://worktile.com/kb/p/48349