C和C++中的##和#

一、C和C++中#

C和C++中的#和宏一起使用,表示将#后面的内容转换为字符串

示例

#define TEST(n) #n
int main(int argc, char const *argv[])
{
	cout<<TEST(9)<<endl;
	cout<<TEST(qwe)<<endl;
	return 0;
}

上述代码中,当执行TEST(9)和TEST(qwe)时,会将其分别替换为#9和#qwe,进而将#9和#qwe转换为"9"he"qwe",于是乎就出现了上述输出结果

注意:不能直接输出#9和#qwe,否则报错

int main(int argc, char const *argv[])
{
	cout<<#9<<endl;
	cout<<#qwe<<endl;
	return 0;
}

#的应用

比如QT4源码中SIGNAL和SLOT的实现如下

# define SLOT(a)     "1"#a
# define SIGNAL(a)   "2"#a

当写下下面的代码时

connect(sender, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));

就会被转化为这样

connect(sender, "2destroyed()", this, "1objectDestroyed()");

 

二、C和C++中##

##一般用来连接两个名字

示例

#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
  test_suite_name##_##test_name##_Test

void GTEST_TEST_CLASS_NAME_(a,b)() {cout<<__func__<<endl;}

int main(int argc, char const *argv[])
{
	GTEST_TEST_CLASS_NAME_(a, b)();
	return 0;
}

上述代码通过##定义了一个函数,并打印出函数的名字,通过打印结果可以看出,test_suite_name被a替换,test_name被b替换,最终输出a_b_Test

##的应用

##在C++框架的编写中应用的非常广泛,通过##和宏的参数,可以用来定义出各种不同的类,比如gtest框架中的下面的3段代码

#define TEST_F(test_fixture, test_name)\
  GTEST_TEST_(test_fixture, test_name, test_fixture, \
              ::testing::internal::GetTypeId<test_fixture>())

#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id)      \
  static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1,                \
                "test_suite_name must not be empty");                         \
  static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1,                      \
                "test_name must not be empty");                               \
  class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                    \
      : public parent_class {                                                 \
   public:                                                                    \
    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() = default;           \
    ~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default; \
    GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name,   \
                                                           test_name));       \
    GTEST_DISALLOW_MOVE_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name,   \
                                                           test_name));       \
                                                                              \
   private:                                                                   \
    void TestBody() override;                                                 \
    static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;     \
  };                                                                          \
                                                                              \
  ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name,          \ //对TestInfo进行初始化并添加至测试case的vector
                                                    test_name)::test_info_ =  \
      ::testing::internal::MakeAndRegisterTestInfo(                           \
          #test_suite_name, #test_name, nullptr, nullptr,                     \
          ::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \
          ::testing::internal::SuiteApiResolver<                              \
              parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__),         \
          ::testing::internal::SuiteApiResolver<                              \
              parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__),      \
          new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_(    \//TestFactoryImpl是TestFactoryBase的子类
              test_suite_name, test_name)>);                                  \
  void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()//函数体由用户自行添加

#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ //生成类名
  test_suite_name##_##test_name##_Test

上述三段代码通过GTEST_TEST_CLASS_NAME_和参数,生成不同的名字,再通过GTEST_TEST_来抽象出各个类中都要有的函数,从而创建出功能类似的类和对象,达到抽象和封装的目的

再比如QT框架中的这段代码

#define Q_DECLARE_PRIVATE(Class) \
    inline Class##Private* d_func() \
    { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
    inline const Class##Private* d_func() const \
    { Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
    friend class Class##Private;

d_func通过##的连接,将返回值抽象为Class##Private的指针,具体类型会在预编译阶段将Class替换为具体的名字,比如,当传入A时,返回值就是APrivate *

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值