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",于是乎就出现了上述输出结果
int main(int argc, char const *argv[])
{
cout<<#9<<endl;
cout<<#qwe<<endl;
return 0;
}
# 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_来抽象出各个类中都要有的函数,从而创建出功能类似的类和对象,达到抽象和封装的目的
#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 *