c/c++ 奇技淫巧(一些c语言的技巧)

2020-01-06 16:59:17刘景俊


#define PARAM( x ) #x 
  #define ADDPARAM( x ) INT_##x 

PARAM( ADDPARAM( 1 ) ); 将被展开为”ADDPARAM( 1 )”。

所以此时要得到“INT_1”的结果,必须加入一个中间宏:


#define PARAM(x) PARAM1(x)
#define PARAM1( x ) #x 

PARAM( ADDPARAM( 1 ) );此时的结果将会是“INT_1”。根据prescan原则,当ADDPARAM(1)传入,会展开得到INT_1,然后将INT_1带入PARAM1宏,最终得到“INT_1”的结果。

4. 接口宏

以下部分,摘自网上博客,仅作声明。
C++的目标之一就是把类的声明和定义分离开来,这对于项目的开发极其有利——这可以使开发人员不用看到类的实现就能知晓类的功能。但是,C++实现类的声明与类定义的分离的方法会导致一些额外的工作——每个非内联函数的表示都需要写两次,一次在类声明中,一次在类定义中。
代码如下:


// .h File 
class Element 
{ 
void Tick (); 
};

// .cpp File 
void Element ::Tick () 
{ 
// todo 
}

由于Tick的标识在两个地方都出现了,因此如果我们需要改变这个方法的参数的时候(改变函数名、返回类型或者加const),我们需要改变两个地方。
当然通常这没有什么工作量,但是有些情况下这个特性会带来不少麻烦。
举个例子,如果我们有一个叫做BaseClass的基类,有三个从BaseClass继承而来的子类——D1、D2和D3.其中BaseClass声明了一个虚函数Foo()并且有一个缺省实现,并且D1、D2、D3中重载了Foo()函数。
现在,如果说我们给BaseClass::Foo()添加一个参数,但是忘了给D3中做相应的修改。麻烦来了——编译可以通过,编译器会把BaseClass::Foo(…)和D3::Foo()当成两个完全不同的函数。当我们想通过虚函数机制来调用D3的Foo的时候,这就容易出一些问题。
UE4中光继承自AActor类的类就有上千个,如果需要对AActor类做一个修改,那么如果使用传统方法,我们还要针对上千个派生类进行修改,而且万一有一个派生类没有修改,编译器也不会报错!
这么看来,理想的情况是我们希望一个函数的表示只在一个地方存在,如果说只声明BaseClass::Foo()一次,然后再它的派生类中不用再额外声明Foo就好了。
而且在效率方面来说,在C++中使用继承的时候我们经常会使用很多浅层次的类继承关系,一个父类往往有一堆子类。很多时候我们只需要把很多互不相关的功能集成到一个单独的类继承家族里面。
对于浅继承来说,我们只是把开始的父类声明为一个接口——也就是说它声明了一些虚函数(大部分是纯虚函数)。在大多数情况下,我们会在这个类家族里面有一个基类以及其余的派生类。