如何让基类Movie强制子类实现同类型对象的比较方法?
实现基类强制子类重写自身类型参数的比较方法
要实现基类强制子类使用自身类类型作为比较参数,你可以结合**奇异递归模板模式(CRTP)**和纯虚函数来达成目标。这种方式既能让基类约束子类必须实现特定签名的方法,又能保证类型安全。
步骤1:定义顶层抽象基类 Movie
先定义最顶层的抽象基类,作为所有子类的公共接口:
#include <stdexcept> class Movie { public: // 统一的对外比较接口(用于多态场景) virtual bool compare(const Movie& other) const = 0; virtual ~Movie() = default; };
步骤2:创建CRTP模板基类
这个模板类继承自Movie,并定义一个纯虚函数,参数为子类自身类型,以此强制子类必须实现该方法:
template<typename Derived> class MovieCRTP : public Movie { public: // 强制子类实现接收自身类型参数的比较方法 virtual bool compare(const Derived& other) const = 0; // 实现顶层基类的compare接口,内部调用子类的类型安全版本 bool compare(const Movie& other) const override { // 动态类型检查,确保比较对象是相同子类类型 const Derived* derived_other = dynamic_cast<const Derived*>(&other); if (!derived_other) { throw std::invalid_argument("Cannot compare different types of movies"); } // 调用子类的类型安全比较方法 return compare(*derived_other); } };
步骤3:实现具体子类
每个子类继承MovieCRTP<自身类型>,并必须重写compare(const 自身类型&)方法:
// Comedy子类 class Comedy : public MovieCRTP<Comedy> { private: int laughter_rating; // 喜剧特有的属性,用于比较 public: Comedy(int rating) : laughter_rating(rating) {} // 必须实现接收Comedy类型参数的compare方法 bool compare(const Comedy& other) const override { return this->laughter_rating == other.laughter_rating; } }; // Drama子类 class Drama : public MovieCRTP<Drama> { private: int emotional_depth; // 剧情片特有的属性 public: Drama(int depth) : emotional_depth(depth) {} bool compare(const Drama& other) const override { return this->emotional_depth == other.emotional_depth; } }; // Classical子类 class Classical : public MovieCRTP<Classical> { private: int era; // 古典片特有的属性 public: Classical(int era) : era(era) {} bool compare(const Classical& other) const override { return this->era == other.era; } };
关键说明
- 强制约束:如果子类没有实现
compare(const Derived&),编译器会直接报错——因为MovieCRTP中的该方法是纯虚函数,子类必须提供实现。 - 类型安全:通过
dynamic_cast在顶层compare接口中做类型检查,确保只有相同类型的子类才能比较,避免跨类型比较的逻辑错误。 - 多态支持:顶层
Movie类的compare(const Movie&)接口保留了多态性,你可以用Movie*或const Movie&来操作所有子类对象,同时内部会自动调用类型安全的比较逻辑。
测试示例
#include <iostream> int main() { Comedy c1(8), c2(8), c3(9); Drama d1(7), d2(7); // 同类型比较 std::cout << std::boolalpha; std::cout << c1.compare(c2) << std::endl; // true std::cout << c1.compare(c3) << std::endl; // false std::cout << d1.compare(d2) << std::endl; // true // 多态场景下的比较 const Movie& m1 = c1; const Movie& m2 = c2; std::cout << m1.compare(m2) << std::endl; // true // 跨类型比较会抛出异常 try { m1.compare(d1); } catch (const std::invalid_argument& e) { std::cout << e.what() << std::endl; // 输出"Cannot compare different types of movies" } return 0; }
内容的提问来源于stack exchange,提问作者Antonymous1337
相关产品推荐
相关产品推荐

