#ifndef MYSPDLOG_H #define MYSPDLOG_H #include <fstream> #include <iostream> #define SPDLOG_HEADER_ONLY #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG #include "spdlog/spdlog.h" #include "spdlog/logger.h" #include "spdlog/sinks/basic_file_sink.h" #include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/sinks/stdout_color_sinks.h" #include "spdlog/sinks/daily_file_sink.h" class MySpdlog { public: static MySpdlog*getInstace() { static MySpdlog MySpdlogStatic; return &MySpdlogStatic; } int init() { std::string formatStr="%Y-%m-%dT%H:%M:%S.%e[%l][%s:%#][%!]%v"; // auto myLogger1 = std::make_sharedspdlog::sinks::rotating_file_sink_mt("spdlog", "logs/myspdlog.log", 1024 * 1024 * 10, 10); // auto myLogger1 = std::make_sharedspdlog::sinks::daily_file_sink("spdlog", "logs/log.txt", 0, 0); auto myLogger1 = spdlog::daily_logger_mt("spdlog", "logs/log.txt", 0, 0); // myLogger1 = spdlog::rotating_logger_mt("spdlog", "logs/myspdlog.log", 1024 * 1024 * 10, 10); spdlog::set_default_logger(myLogger1); myLogger1->set_level(spdlog::level::debug); myLogger1->set_pattern(formatStr); myLogger2 = spdlog::stdout_color_mt("baseLogger2"); spdlog::set_default_logger(myLogger2); myLogger2->set_level(spdlog::level::debug); myLogger2->set_pattern(formatStr); return 0; } void uninit() { } static std::shared_ptrspdlog::logger myLogger1; static std::shared_ptrspdlog::logger myLogger2; private: MySpdlog() {} ~MySpdlog() {} }; std::shared_ptrspdlog::logger MySpdlog::myLogger1; std::shared_ptrspdlog::logger MySpdlog::myLogger2; #define SPLOG_INIT() MySpdlog::getInstace()->init() #define SPLOG_UNINIT() MySpdlog::getInstace()->uninit() #define SPLOG_DEBUG(...) do {SPDLOG_LOGGER_DEBUG(MySpdlog::myLogger1, VA_ARGS);\ SPDLOG_LOGGER_DEBUG(MySpdlog::myLogger2, VA_ARGS);}while(0) #define SPLOG_INFO(...) do {SPDLOG_LOGGER_INFO(MySpdlog::myLogger1, VA_ARGS);\ SPDLOG_LOGGER_INFO(MySpdlog::myLogger2, VA_ARGS);}while(0) #define SPLOG_ERROR(...) do {SPDLOG_LOGGER_ERROR(MySpdlog::myLogger1, VA_ARGS);\ SPDLOG_LOGGER_ERROR(MySpdlog::myLogger2, VA_ARGS);}while(0) #define SPDLOG_CLRAR(a) do{std::fstream fout((a),std::ios::out|std::ios::trunc);fout.close();}while(0); #endif // MYSPDLOG_H这样写完编译后报错:-1: error: main.o:(.bss+0x10): multiple definition of `MySpdlog::myLogger2'; csocketfactory.o:(.bss+0x10): first defined here
时间: 2024-03-29 07:38:28 浏览: 129
根据错误提示,MySpdlog::myLogger2 被定义了多次,这是因为在头文件中定义了静态成员变量,而这个头文件被多个源文件包含,导致重复定义。解决办法是将静态成员变量的定义移到 .cpp 文件中,或者使用 inline 定义静态成员变量。
另外,头文件中定义的宏应该使用 #pragma once 或者 #ifndef/#define/#endif 来避免重复包含。同时,宏定义中的 VA_ARGS 应该改为 __VA_ARGS__。
相关问题
#ifndef MYSPDLOG_H #define MYSPDLOG_H #include <fstream> #include <iostream> #define SPDLOG_HEADER_ONLY #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG #include "spdlog/spdlog.h" #include "spdlog/logger.h" #include "spdlog/sinks/basic_file_sink.h" #include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/sinks/stdout_color_sinks.h" #include "spdlog/sinks/daily_file_sink.h" class MySpdlog { public: static MySpdlog*getInstace() { static MySpdlog MySpdlogStatic; return &MySpdlogStatic; } int init() { std::string formatStr="%Y-%m-%dT%H:%M:%S.%e[%l][%s:%#][%!]%v"; // auto myLogger1 = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("spdlog", "logs/myspdlog.log", 1024 * 1024 * 10, 10); // auto myLogger1 = std::make_shared<spdlog::sinks::daily_file_sink>("spdlog", "logs/log.txt", 0, 0); auto myLogger1 = spdlog::daily_logger_mt("spdlog", "logs/log.txt", 0, 0); // myLogger1 = spdlog::rotating_logger_mt("spdlog", "logs/myspdlog.log", 1024 * 1024 * 10, 10); spdlog::set_default_logger(myLogger1); myLogger1->set_level(spdlog::level::debug); myLogger1->set_pattern(formatStr); myLogger2 = spdlog::stdout_color_mt("baseLogger2"); spdlog::set_default_logger(myLogger2); myLogger2->set_level(spdlog::level::debug); myLogger2->set_pattern(formatStr); return 0; } void uninit() { } std::shared_ptr<spdlog::logger> myLogger1; std::shared_ptr<spdlog::logger> myLogger2; private: MySpdlog() {} ~MySpdlog() {} }; #define SPLOG_INIT() MySpdlog::getInstace()->init() #define SPLOG_UNINIT() MySpdlog::getInstace()->uninit() #define SPLOG_DEBUG(...) do {SPDLOG_LOGGER_DEBUG(MySpdlog::getInstace()->myLogger1, __VA_ARGS__);\ SPDLOG_LOGGER_DEBUG(MySpdlog::getInstace()->myLogger2, __VA_ARGS__);}while(0) #define SPLOG_INFO(...) do {SPDLOG_LOGGER_INFO(MySpdlog::getInstace()->myLogger1, __VA_ARGS__);\ SPDLOG_LOGGER_INFO(MySpdlog::getInstace()->myLogger2, __VA_ARGS__);}while(0) #define SPLOG_ERROR(...) do {SPDLOG_LOGGER_ERROR(MySpdlog::getInstace()->myLogger1, __VA_ARGS__);\ SPDLOG_LOGGER_ERROR(MySpdlog::getInstace()->myLogger2, __VA_ARGS__);}while(0) #define SPDLOG_CLRAR(a) do{std::fstream fout((a),std::ios::out|std::ios::trunc);fout.close();}while(0); #endif // MYSPDLOG_H运行之后调用SPLOG_INFO时报错
根据您提供的代码,我看到您定义了一个名为`SPLOG_INFO`的宏,其实现方式为:
```
#define SPLOG_INFO(...) do {SPDLOG_LOGGER_INFO(MySpdlog::getInstace()->myLogger1, __VA_ARGS__);\
SPDLOG_LOGGER_INFO(MySpdlog::getInstace()->myLogger2, __VA_ARGS__);}while(0)
```
这个宏展开后会调用`SPDLOG_LOGGER_INFO`来输出日志信息,而`SPDLOG_LOGGER_INFO`需要传入一个有效的logger对象作为第一个参数。在您的代码中,您定义了一个名为`myLogger1`的logger对象,但是您没有在宏中使用它,而是在`MySpdlog`类中以成员变量的形式定义。因此,当您调用`SPLOG_INFO`时,会找不到有效的logger对象,从而导致编译错误。
要解决这个问题,您可以将`myLogger1`和`myLogger2`定义为静态成员变量,并在`MySpdlog`类外初始化它们。然后,在宏中使用这两个静态成员变量。
例如,您可以将`MySpdlog`类的定义改为:
```
class MySpdlog {
public:
static MySpdlog*getInstace()
{
static MySpdlog MySpdlogStatic;
return &MySpdlogStatic;
}
int init()
{
std::string formatStr="%Y-%m-%dT%H:%M:%S.%e[%l][%s:%#][%!]%v";
auto myLogger1 = spdlog::daily_logger_mt("spdlog", "logs/log.txt", 0, 0);
spdlog::set_default_logger(myLogger1);
myLogger1->set_level(spdlog::level::debug);
myLogger1->set_pattern(formatStr);
auto myLogger2 = spdlog::stdout_color_mt("baseLogger2");
spdlog::set_default_logger(myLogger2);
myLogger2->set_level(spdlog::level::debug);
myLogger2->set_pattern(formatStr);
return 0;
}
void uninit()
{
}
static std::shared_ptr<spdlog::logger> myLogger1;
static std::shared_ptr<spdlog::logger> myLogger2;
private:
MySpdlog() {}
~MySpdlog() {}
};
std::shared_ptr<spdlog::logger> MySpdlog::myLogger1;
std::shared_ptr<spdlog::logger> MySpdlog::myLogger2;
```
然后,您可以在代码的其他地方使用这两个静态成员变量。例如,在`SPLOG_INFO`中,您可以这样使用:
```
#define SPLOG_INFO(...) \
do { \
SPDLOG_LOGGER_INFO(MySpdlog::myLogger1, __VA_ARGS__); \
SPDLOG_LOGGER_INFO(MySpdlog::myLogger2, __VA_ARGS__); \
} while(0)
```
这样,当您调用`SPLOG_INFO`时,就会使用正确的logger对象输出日志信息,从而避免编译错误。
// // Created by mcumbrella on 23-5-22. // #ifndef GAMEOFLIFE_AUTOMATON_H #define GAMEOFLIFE_AUTOMATON_H #include <vector> #include <iostream> #include <fstream> #include <string> #include "Cell.h" class Automaton { public: Automaton(int lines, int columns); void init(bool generateRandom = false); // 初始化网格 void run(); // 执行一代演化 void display(); // 显示网格的当前状态 void saveToFile(std::string filename); // 将当前一代保存到文件中 void loadFromFile(std::string filename); // 加载之前保存的一代 void changeCellState(int x, int y); // 更改细胞状态 void revertToPreviousGeneration(); // 返回到前一代的状态 private: int lines; // 网格大小 int columns; std::vector<std::vector<Cell>> grid; // 网格 std::vector<std::vector<Cell>> previousGeneration; // 上一代网格 bool hasPreviousGeneration = false; // 是否有上一代网格 void evolve(); // 演化网格 int countLiveNeighbors(int x, int y); // 统计活邻居的数量 }; #endif //GAMEOFLIFE_AUTOMATON_H介绍代码思路
这个代码实现了 Game of Life 生命游戏的自动机类,其中 `Automaton` 类包含了一些常用的操作函数,如初始化、执行演化、显示网格状态、保存和加载文件等。类中包含了一个二维向量 `grid`,表示网格中的每个细胞的状态,以及一个二维向量 `previousGeneration`,用于保存上一代的状态。在演化过程中,会根据细胞周围的状态来判断细胞下一代的状态,并将当前状态保存到 `previousGeneration` 中。同时,该类还包含了一些实用函数,如更改细胞状态、统计活邻居数量等。通过这些函数的组合,可以实现 Game of Life 生命游戏的自动化演化过程。
阅读全文