使用sstream导致自定义异常类拷贝构造函数被隐式删除报错问题
问题根因
报错核心原因是:std::stringstream 类型不支持拷贝构造,你把它定义为tornadoException类的成员变量后,C编译器会自动删除该类的默认拷贝构造函数。而C抛出异常的底层逻辑要求异常对象必须支持拷贝构造,因此触发编译报错。
你的代码中ss成员仅在带参构造函数里用来拼接字符串,转成message存储后就没有其他用途,完全没必要作为类成员存在,属于冗余设计导致的问题。
解决方案(最优,改动最小)
直接删除类的stringstream成员变量,拼接逻辑改为在构造函数内定义局部stringstream即可:
1. 修改 tornadoException.h
删除私有块里的stringstream ss;行,同时建议移除头文件的using namespace std;避免全局命名空间污染:
#ifndef tornadoException_h #define tornadoException_h #include <string> class tornadoException{ public: tornadoException(); tornadoException(int m); std::string what(); private: std::string message; }; #endif
2. 修改 tornadoException.cpp 带参构造函数
把原来用成员ss的逻辑改为局部变量:
tornadoException::tornadoException(int m){ std::stringstream ss; // 局部变量,用完自动销毁,不会影响类的拷贝构造 ss << "Tornado: " << m << " miles away! and approaching!"; message = ss.str(); }
可选优化
catch异常时建议用常量引用接收,避免不必要的对象拷贝,也能兼容更多特殊的异常类设计:
catch(const tornadoException& tornadoObj){ cout << tornadoObj.what(); }
其他可选方案(仅作原理说明,不推荐)
如果你确实需要把stringstream作为类成员保留,可以把成员改为std::unique_ptr<std::stringstream>智能指针,手动实现类的拷贝构造函数,将旧对象ss.str()的内容写入新对象的stringstream即可,但该方案会增加不必要的性能开销和代码复杂度,异常类场景下完全不需要。
内容的提问来源于stack exchange,提问作者jordanpaulee
相关产品推荐
相关产品推荐

