函数模板中打印类指针成员字符串的问题排查与解决
函数模板中处理不同类的字符串成员问题排查与解决
咱们先逐个揪出你代码里的问题,再一步步解决怎么在模板里打印不同类的字符串成员:
代码里的错误点
- Queue类未模板化:你在Queue里用了
T类型,但没把Queue声明为模板类,编译器根本不知道T是什么,这是最核心的语法错误。 - 未初始化的野指针:
main里的Test2 *new_val和Queue *data都是空指针,既没给new_val分配Test2对象,也没给data分配Queue对象,直接调用data->append(new_val)会导致程序崩溃或者未定义行为。 - 缺少必要头文件:代码里用了
std::mutex和std::lock_guard,但没包含<mutex>头文件,编译器会报错找不到这些类型。 - 遗漏mutex成员变量:Queue类里用了
std::lock_guard<std::mutex> lock(mutex),但根本没声明std::mutex mutex这个成员变量,编译肯定通不过。 - 参数与容器类型不匹配:你的
mQueue是std::vector<T>,但append的参数是T & item,结合你传指针的用法,这里的参数类型和成员访问方式(item->val2)需要适配指针/对象两种场景。
修复后的代码示例
下面是修复好的完整代码,关键修改点都加了注释:
#include <iostream> #include <string> #include <vector> #include <mutex> // 新增:包含mutex头文件 #include <iterator> using namespace std; template <typename T> class Test1{ public: int val1 = 10; string val2 = "hello"; }; class Test2{ public: int val1 = 20; string val2 = "hai"; }; // 修改:把Queue改成模板类,声明模板参数T template <typename T> class Queue{ public: // 重载1:处理对象类型的参数 void append(const T& item) { std::lock_guard<std::mutex> lock(m_mutex); cout<<"string to be added: "<<item.val2<<endl; mQueue.push_back(item); } // 重载2:处理指针类型的参数 void append(T* item) { if (item == nullptr) { // 先判断指针不为空,避免崩溃 cout<<"error: null pointer passed"<<endl; return; } std::lock_guard<std::mutex> lock(m_mutex); cout<<"string to be added: "<<item->val2<<endl; mQueue.push_back(*item); // 如果容器存对象就解引用,存指针就直接push_back(item) } private: std::vector<T> mQueue; std::mutex m_mutex; // 新增:声明mutex成员变量 }; int main(int argc, char** argv) { // 修改:初始化指针,分配内存 Test2* new_val = new Test2(); // 修改:初始化Queue,指定模板类型为Test2 Queue<Test2>* data = new Queue<Test2>(); data->append(new_val); // 额外测试Test1的场景 Test1<int> test1_obj; Queue<Test1<int>> test1_queue; test1_queue.append(test1_obj); // 记得释放内存,避免内存泄漏 delete new_val; delete data; return 0; }
怎么在函数模板中打印不同类的字符串成员
因为你的Test1和Test2都有同名的val2字符串成员,模板可以利用鸭子类型(只要类型有对应成员,编译器就会通过)来访问,这里有几种常用方法:
- 直接访问共同成员:如果所有要处理的类都有
val2成员,模板函数里直接写item.val2(对象)或者item->val2(指针)即可,编译器会自动推导类型并访问对应的成员。 - 适配对象/指针双场景:如果模板可能接收对象或者指针,可以通过重载函数、模板特化,或者C++17的
if constexpr做分支判断:template <typename T> void printVal2(const T& item) { if constexpr (std::is_pointer_v<T>) { if (item != nullptr) { cout << item->val2 << endl; } } else { cout << item.val2 << endl; } } - 约束模板的适用范围(C++20+):如果担心有些类没有
val2成员,可以用C++20的概念来约束模板只能接受符合要求的类型:template <typename T> concept HasStringVal2 = requires(T t) { { t.val2 } -> std::same_as<std::string&>; }; template <HasStringVal2 T> void append(const T& item) { // 这里可以安全访问item.val2 }
内容的提问来源于stack exchange,提问作者VBurman
相关产品推荐
相关产品推荐

