能否编写通用深度比较函数?对比未重载operator==的类对象
可以编写这样的通用深度比较函数吗?
答案是可以实现,但需要解决几个关键问题,同时存在一定局限性,下面逐一拆解:
核心前提:成员访问权限
你给出的Class1和Class2成员默认是私有(private)的,模板函数Compare无法直接访问这些成员。解决方式有两种:
- 将类的成员改为公有(
public) - 在类中声明
Compare模板为友元
比如修改Class1:
class Class1 { int i; int *pi; // 声明友元,让Compare能访问私有成员 template<typename T> friend bool Compare(T obj1, T obj2); };
深度比较的实现思路
要实现深度比较,需要针对不同类型的成员做差异化处理:
- 对于基本数据类型(
int、char等):直接用==比较 - 对于指针类型:先判断指针是否都为空(两个空指针视为相等),若非空则解引用后递归比较指向的值
- 对于自带
operator==的类型(比如std::string):直接调用其自身的比较逻辑 - 对于自定义类类型:递归调用
Compare函数比较其内部成员
代码实现示例
利用C++的类型萃取(如std::is_pointer、std::is_fundamental)和SFINAE(替换失败不是错误)实现类型分支:
#include <type_traits> #include <string> // 处理自定义类(非指针、非基本类型) template<typename T> typename std::enable_if<!std::is_pointer<T>::value && !std::is_fundamental<T>::value, bool>::type Compare(const T& obj1, const T& obj2) { // 手动适配每个自定义类的成员比较逻辑 if constexpr (std::is_same_v<T, Class1>) { return obj1.i == obj2.i && Compare(obj1.pi, obj2.pi); } else if constexpr (std::is_same_v<T, Class2>) { return obj1.c == obj2.c && Compare(obj1.pc, obj2.pc) && Compare(obj1.ps, obj2.ps); } // 其他自定义类需在此添加分支 else { static_assert(std::is_void_v<T>, "Unsupported type for Compare"); return false; } } // 处理指针类型 template<typename T> typename std::enable_if<std::is_pointer<T>::value, bool>::type Compare(const T& ptr1, const T& ptr2) { if (!ptr1 && !ptr2) return true; if (!ptr1 || !ptr2) return false; return Compare(*ptr1, *ptr2); } // 处理基本数据类型 template<typename T> typename std::enable_if<std::is_fundamental<T>::value, bool>::type Compare(const T& val1, const T& val2) { return val1 == val2; } // 复用std::string自带的比较逻辑 template<> bool Compare(const std::string& s1, const std::string& s2) { return s1 == s2; } // 自定义类声明(带友元) class Class1 { int i; int *pi; template<typename T> friend bool Compare(const T& obj1, const T& obj2); }; class Class2 { char c; char *pc; std::string *ps; template<typename T> friend bool Compare(const T& obj1, const T& obj2); }; // 使用示例 int main() { Class1 a1, b1; // 初始化逻辑... bool c1 = Compare(a1, b1); Class2 a2, b2; // 初始化逻辑... bool c2 = Compare(a2, b2); return 0; }
关键局限性
- 无法完全自动适配所有自定义类:上述实现需要手动为每个自定义类添加成员比较分支,除非使用C++20及以后的实验性反射特性,否则无法自动遍历类的所有成员。
- 循环引用风险:如果类中存在指向自身的指针(如
Class1包含Class1*成员),递归比较会导致栈溢出。 - 未初始化指针的未定义行为:若指针未初始化,解引用会触发UB,需确保传入对象已正确初始化。
- 智能指针需额外处理:如果类中使用
std::unique_ptr、std::shared_ptr等智能指针,需单独适配比较逻辑(比如比较指向的对象而非控制块地址)。
内容的提问来源于stack exchange,提问作者Pietro
相关产品推荐
相关产品推荐

