Question List in May, 2023

1、工作记录

工作内容不对外公开。

2、日常积累

#cplusplus

2.1 C++ 实现 LOG 输出

可以在析构函数中输出换行符以便使用 LOG(INFO) << "hello" 时直接在末尾添加换行符,另外需要注意的就是宏展开中 ## 是用于宏代码的拼接,可以将括号内的参数直接拼接到内容中。

class LogMessage{
public:
    LogMessage(std::string message):_message(message){}
    ~LogMessage(){
        std::cout << std::endl;
    }
    std::ostream& stream(){
        std::ostream& os = std::cout;
        os << "[" << _message << "]: ";
        return os;
    }
private:
    std::string _message;
};
#define COMPACT_LOG_INFO LogMessage("INFO")
#define COMPACT_LOG_WARNING LogMessage("WARNING")
#define COMPACT_LOG_ERROR LogMessage("ERROR")
#define LOG(severity) COMPACT_LOG_ ## severity.stream()

2.2 C++ 反射机制

如果要实现反射,一般来实现有两种:一种是静态反射,利用宏和模板在编译器就将反射函数对应展开,因此没有什么开销;另一类是动态反射,程序中对每一个注册过反射类型的对象保存着一张表,通过查找表去做相应动作。总体来说,任何语言实现反射都离不开保存一张查找表,然后对应展开的过程,无非就是静态动态,编译器做还是用户做了。

#include <unordered_map>
#include <string>
#include <iostream>
#include <stdlib.h>

class Test
{
public:
     void a(){std::cout<<"I am a"<<std::endl;}
     void b(){std::cout<<"I am b"<<std::endl;}
     void c(){std::cout<<"I am c"<<std::endl;}
     std::unordered_map<std::string,void (Test::*)()>funcList;
     Test(){
             funcList.emplace("a",&Test::a);
             funcList.emplace("b",&Test::b);
             funcList.emplace("c",&Test::c);
     };
public:
     void demo(){
         (this->*funcList.at("c"))();
     }
};

int main(void){
     Test test;
     void (Test::*ptr)()=test.funcList.at("a");
     (test.*ptr)();                   // 第一种调用方法
     (test.*test.funcList.at("b"))(); // 第二种调用方法
     test.demo();                     // 第三种调用方法
     return 0;
}

//结果:
//I am a
//I am b
//I am c

参考文献

  1. 知乎. # 借助宏和模板技术实现C++的简单静态反射[EB/OL].

  2. 知乎. # C++模板寄算:简单的成员反射[EB/OL].

  3. 知乎. # 如何优雅的实现C++编译期静态反射[EB/OL].

  4. CSDN 博客. # C++ 对象的成员函数反射[EB/OL].

  5. CSDN 博客. # C++语言学习(十四)——C++类成员函数调用分析[EB/OL].

  6. CSDN 博客. # C++类成员函数模拟实现反射[EB/OL].