C++是否存在默认对象方法机制,可让自定义类对象直接使用时自动触发逻辑
C++自定义类默认输出方法实现方案
问题背景
你编写的模板归并排序代码如下,int、float、std::string类型都可以正常运行,但传入自定义CInstance类时在display函数输出阶段编译失败,需求是让CInstance对象被std::cout直接输出时自动触发预设的处理逻辑:
#include <iostream> #include <vector> #include <string> // 尝试创建默认方法调用 class CInstance { private: std::string str_; public: CInstance(const std::string& str) : str_(str) {} bool const operator>(const CInstance& that){ return (this->str_.size() > that.str_.size());} }; template<class T> class CObj { private: T val; public: CObj(const T n) : val(n) {} T Get() { return val; } }; template<class T> using vcobj = std::vector<CObj<T>>; template<class T> void display(vcobj<T>& v) { for (auto &i : v) { std::cout << i.Get() << " "; } std::cout << "\n"; } template<class T> vcobj<T> Merge(vcobj<T>& lv, vcobj<T>& rv) { vcobj<T> ret; auto lsize = lv.size(); auto rsize = rv.size(); unsigned int lpin = 0, rpin = 0; while(lpin < lsize && rpin < rsize) { if(lv.at(lpin).Get() > rv.at(rpin).Get()) { ret.emplace_back(rv.at(rpin).Get()); rpin++; } else { ret.emplace_back(lv.at(lpin).Get()); lpin++; } } for (auto i=lpin; i<lsize; i++) { ret.emplace_back(lv.at(i).Get()); } for (auto i=rpin; i<rsize; i++) { ret.emplace_back(rv.at(i).Get()); } return ret; } template<class T> vcobj<T> Sort(const vcobj<T>& v) { vcobj<T> ret; auto size = v.size(); if(size == 0) { return ret; } if(size > 1) { auto mid = size / 2; vcobj<T> l(v.begin(), v.begin()+mid); auto lv = Sort(l); vcobj<T> r(v.begin()+mid, v.end()); auto rv = Sort(r); ret = Merge(lv, rv); } else { ret = v; } return ret; } int main() { { vcobj<int> v = {4, 5, 2, 1, 9, 6, 10, 8, 15, 3, 7}; display(v); auto sorted = Sort(v); display(sorted); } { vcobj<float> v = {0.01, 0.001, 0.002, 0.009, 0.010, 0.0003, 0.00001}; display(v); auto sorted = Sort(v); display(sorted); } { vcobj<std::string> v = {{"pineapple"}, {"jackfruit"}, {"mango"}, {"apple"}, {"banana"}}; display(v); auto sorted = Sort(v); display(sorted); } // 此处触发问题 { vcobj<CInstance> v = {{"pineapple"}, {"jackfruit"}, {"mango"}, {"apple"}, {"banana"}}; display(v); auto sorted = Sort(v); display(sorted); } return 0; }
实现方案
C++有两种成熟的实现机制可以满足需求:
方案1:重载std::ostream的<<运算符(推荐)
这是自定义类输出的标准实现,逻辑可控,不会产生额外的隐式转换风险,只需要给CInstance类添加友元重载函数即可:
class CInstance { private: std::string str_; public: CInstance(const std::string& str) : str_(str) {} // 建议给operator>加上const修饰,符合const正确性要求 bool const operator>(const CInstance& that) const { return (this->str_.size() > that.str_.size()); } // 声明友元,允许运算符函数访问私有成员 friend std::ostream& operator<<(std::ostream& os, const CInstance& obj); }; // 实现输出逻辑,可自定义输出内容 std::ostream& operator<<(std::ostream& os, const CInstance& obj) { // 示例输出存储的字符串,也可输出字符串长度等其他自定义内容 os << obj.str_; return os; }
方案2:重载隐式类型转换运算符
如果你希望CInstance对象在被需要对应类型的场景下自动提取内部值,可以重载类型转换运算符,效果类似自动调用默认get方法:
class CInstance { private: std::string str_; public: CInstance(const std::string& str) : str_(str) {} bool const operator>(const CInstance& that) const { return (this->str_.size() > that.str_.size()); } // 隐式转换为std::string,当需要std::string的场景会自动调用 operator std::string() const { return str_; } };
注意:隐式类型转换使用便捷,但可能触发非预期的自动类型转换,导致逻辑bug,仅建议在明确需求的场景下使用。
修改完成后,CInstance类就可以支持std::cout直接输出,原代码运行不会再报错。
内容的提问来源于stack exchange,提问作者kishoredbn
相关产品推荐
相关产品推荐

