如何替换const char*为std::string并解决重定义编译错误?
问题:err函数重载与重定义错误修复
初始可编译的const char*版本代码
最初的err函数采用const char*参数,可正常编译:
static LISP err(const char* message, LISP x, const char* s) { nointerrupt = 1; if NNULLP(x) { fprintf(stderr, "SIOD ERROR: %s %s: ", (message) ? message : "?", (s) ? s : "" ); lprin1f(x, stderr); fprintf(stderr, "\n"); fflush(stderr); } else { fprintf(stderr, "SIOD ERROR: %s %s\n", (message) ? message : "?", (s) ? s : "" ); fflush(stderr); } if (show_backtrace == 1) display_backtrace(NIL); if (errjmp_ok == 1) { setvar(sym_errobj, x, NIL); longjmp(*est_errjmp, 1); } close_open_files(); /* can give clue to where error is */ fprintf(stderr, "%s: fatal error exiting.\n", siod_prog_name); if (fatal_exit_hook) (*fatal_exit_hook)(); else exit(1); return(NIL); } LISP err(const char* message, LISP x) { return err(message, x, NULL); } LISP err(const char* message, const char* x) { return err(message, NULL, x); }
修改重载函数时的编译错误
尝试拼接字符串修改重载函数后,编译失败:
LISP err(const char* message, const char* x) { std::string full_message = "fromchar_" + std::string(message); return err(full_message.c_str(), NULL, x); } LISP err(const char* message, LISP x) { const char* func_name = "fromlisp_"; // 错误:const char*无法直接与std::string相加,结果是std::string,不能赋值给const char* const char* final_message = (message) ? (func_name + std::string(message)) : "?"; return err(final_message.c_str(), x, NULL); }
编译错误提示:
final_message并非const char*类型
改用std::string后的重定义错误
将参数全部替换为std::string后,出现重定义错误:
static LISP err(const std::string& message, LISP x, const std::string& s) { nointerrupt = 1; if (NNULLP(x)) { fprintf(stderr, "SIOD nullpointer error. Wir wissen aber den typ nicht: %s %s: ", message.c_str(), s.c_str()); lprin1f(x, stderr); fprintf(stderr, "\n"); fflush(stderr); } else { fprintf(stderr, "SIOD anderer error: %s %s\n", message.c_str(), s.c_str()); fflush(stderr); } if (show_backtrace == 1) display_backtrace(NIL); if (errjmp_ok == 1) { setvar(sym_errobj, x, NIL); longjmp(*est_errjmp, 1); } close_open_files(); /* can give clue to where error is */ fprintf(stderr, "%s: fatal error exiting.\n", siod_prog_name); if (fatal_exit_hook) (*fatal_exit_hook)(); else exit(1); return(NIL); } LISP err(const std::string& message, LISP x) { return err("error type A:" + message, x, std::string()); } LISP err(const std::string& message, const std::string& x) { return err("error type B:" + message, LISP(), x); } // 错误:该函数与静态三参数err函数签名完全一致,导致重定义 LISP err(const std::string& message, LISP x, const std::string& x_str) { const std::string func_name = "error from lisp_"; const std::string final_message = (message.empty()) ? "?" : func_name + message; return err(final_message, x, x_str); }
编译错误提示:
slib.cc:733:6: error: redefinition of ‘obj* err(const string&, LISP, const string&)’ 733 | LISP err(const std::string& message, LISP x, const std::string& x_str) | ^~~ slib.cc:696:13: note: ‘obj* err(const string&, LISP, const string&)’ previously defined here 696 | static LISP err(const std::string& message, LISP x, const std::string& s) | ^~
修复方案
方案一:修复std::string版本的重定义问题
重定义错误的核心原因是:最后添加的三参数err函数,与静态的三参数err函数签名完全一致(仅参数名不同,C++中参数名不影响函数签名),因此被视为同一个函数,导致重复定义。
修复步骤:
- 删除重复的三参数重载函数
LISP err(const std::string& message, LISP x, const std::string& x_str)。 - 如果需要给消息添加前缀逻辑,直接在对应的双参数重载函数中实现,调用静态三参数函数即可。
修复后的代码示例:
static LISP err(const std::string& message, LISP x, const std::string& s) { nointerrupt = 1; if (NNULLP(x)) { fprintf(stderr, "SIOD ERROR: %s %s: ", message.empty() ? "?" : message.c_str(), s.empty() ? "" : s.c_str() ); lprin1f(x, stderr); fprintf(stderr, "\n"); fflush(stderr); } else { fprintf(stderr, "SIOD ERROR: %s %s\n", message.empty() ? "?" : message.c_str(), s.empty() ? "" : s.c_str() ); fflush(stderr); } if (show_backtrace == 1) display_backtrace(NIL); if (errjmp_ok == 1) { setvar(sym_errobj, x, NIL); longjmp(*est_errjmp, 1); } close_open_files(); fprintf(stderr, "%s: fatal error exiting.\n", siod_prog_name); if (fatal_exit_hook) (*fatal_exit_hook)(); else exit(1); return(NIL); } LISP err(const std::string& message, LISP x) { std::string final_msg = "fromlisp_" + message; return err(final_msg, x, std::string()); } LISP err(const std::string& message, const std::string& x) { std::string final_msg = "fromchar_" + message; return err(final_msg, LISP(), x); }
方案二:修复原始const char*版本的拼接错误
如果不想切换到std::string,只需修正字符串拼接的错误:const char*不能直接与std::string相加,需要先将const char*转为std::string再拼接,最后用c_str()获取const char*指针。
修复后的代码示例:
static LISP err(const char* message, LISP x, const char* s) { // 保留原实现不变 nointerrupt = 1; if NNULLP(x) { fprintf(stderr, "SIOD ERROR: %s %s: ", (message) ? message : "?", (s) ? s : "" ); lprin1f(x, stderr); fprintf(stderr, "\n"); fflush(stderr); } else { fprintf(stderr, "SIOD ERROR: %s %s\n", (message) ? message : "?", (s) ? s : "" ); fflush(stderr); } if (show_backtrace == 1) display_backtrace(NIL); if (errjmp_ok == 1) { setvar(sym_errobj, x, NIL); longjmp(*est_errjmp, 1); } close_open_files(); fprintf(stderr, "%s: fatal error exiting.\n", siod_prog_name); if (fatal_exit_hook) (*fatal_exit_hook)(); else exit(1); return(NIL); } LISP err(const char* message, LISP x) { std::string final_msg; if (message) final_msg = std::string("fromlisp_") + message; else final_msg = "?"; return err(final_msg.c_str(), x, NULL); } LISP err(const char* message, const char* x) { std::string final_msg; if (message) final_msg = std::string("fromchar_") + message; else final_msg = "?"; return err(final_msg.c_str(), NULL, x); }
内容的提问来源于stack exchange,提问作者tmighty
相关产品推荐
相关产品推荐

