C++子类对象Map存在性检查问题:虚函数未按子类类型比较
问题描述
我用C++编写了代码,定义了Carte基类及CarteScience、CarteFiction等多个子类,使用map<Carte*, int>存储对象指针。我期望通过虚函数Compare根据子类类型判断对象是否已存在,但实际仅按父类Carte类型进行比较。已确认==运算符重载无误,请求协助解决该问题。
代码如下:
#include <iostream> #include <list> #include <vector> #include <string> #include <map> using namespace std; class Carte:public IO{ private: int nrPag; string autor; string nume; public: friend bool operator==(const Carte &obj1, const Carte &obj2){ if(obj1.nrPag!=obj2.nrPag||obj1.autor!=obj2.autor||obj1.nume!=obj2.nume) return 0; return 1; } virtual int Compare(const Carte &obj1){ if(*this==obj1) return 1; return 0; } }; class CarteScience:virtual public Carte{ protected: int an; public: friend bool operator==(const CarteScience &obj1, const CarteScience &obj2){ if((Carte)obj1==(Carte)obj2) if(obj1.an==obj2.an) return 1; return 0; } virtual int Compare(const CarteScience &obj1){ if(*this==obj1) return 1; return 0; } }; class CarteFiction:virtual public Carte{ protected: string univers; float numarCreaturiMagice; public: friend bool operator==(const CarteFiction &obj1, const CarteFiction &obj2){ if((Carte)obj1==(Carte)obj2) if(obj1.univers==obj2.univers&&obj1.numarCreaturiMagice==obj2.numarCreaturiMagice) return 1; return 0; } virtual int Compare(const CarteFiction &obj1){ if(*this==obj1) return 1; return 0; } }; class CarteScienceFiction : public CarteFiction,public CarteScience{ private : double procentReal; public: friend bool operator==(const CarteScienceFiction &obj1, const CarteScienceFiction &obj2){ if((Carte)obj1==(Carte)obj2) if(obj1.univers==obj2.univers&&obj1.numarCreaturiMagice==obj2.numarCreaturiMagice&&obj1.an==obj2.an) return 1; return 0; } int Compare(const CarteScienceFiction &obj1){ if(*this==obj1) return 1; return 0; } }; class Biblioteca{ private: map<Carte*,int> CartiStoc; map<Carte*, int> CartiImprumutate; public: Biblioteca(){ this->CartiStoc= {}; this->CartiImprumutate = {}; } void addStoc(); }; void Biblioteca::addStoc(){ int k; cout << "Tasta 1 pentru carte science Tasta 2 pentru carte fiction Tasta 3 pentru carte science fiction"; cin >> k; switch(k){ case 1:{ CarteScience* aux = new CarteScience(); cin >> *aux; for (auto const& x: CartiStoc) { if((*aux).Compare(*x.first)) cout<<"2"; } this->CartiStoc[aux] = 1; break; } } }
问题原因
你的Compare函数没有实现真正的多态:基类的Compare参数是const Carte&,但子类的Compare参数是各自的子类类型(比如const CarteScience&),这属于函数重载而非函数重写。调用时只会匹配基类的Compare函数,自然只会比较父类成员。
修复方案
1. 统一Compare函数签名,实现多态
将基类的Compare改为纯虚函数,强制子类重写时保持参数为const Carte&:
class Carte : public IO { // ... 原有成员 ... public: virtual ~Carte() = default; // 必须添加虚析构,避免多态下内存泄漏 virtual bool Compare(const Carte& obj) const = 0; // 纯虚函数,统一签名 };
2. 子类重写Compare时先判断类型
在子类的Compare函数中,用dynamic_cast判断传入对象的实际类型,再调用对应==运算符:
class CarteScience : virtual public Carte { // ... 原有成员 ... public: bool Compare(const Carte& obj) const override { const CarteScience* sci_obj = dynamic_cast<const CarteScience*>(&obj); if (sci_obj != nullptr) { return *this == *sci_obj; } return false; // 类型不匹配直接返回false } };
同理修改CarteFiction和CarteScienceFiction:
class CarteFiction : virtual public Carte { // ... 原有成员 ... public: bool Compare(const Carte& obj) const override { const CarteFiction* fic_obj = dynamic_cast<const CarteFiction*>(&obj); if (fic_obj != nullptr) { return *this == *fic_obj; } return false; } }; class CarteScienceFiction : public CarteFiction, public CarteScience { // ... 原有成员 ... public: bool Compare(const Carte& obj) const override { const CarteScienceFiction* scifi_obj = dynamic_cast<const CarteScienceFiction*>(&obj); if (scifi_obj != nullptr) { return *this == *scifi_obj; } return false; } };
3. 修正==运算符的切片问题
子类==中用(Carte)obj1会触发对象切片,仅保留父类部分,改为用基类引用比较:
// 原代码 if((Carte)obj1==(Carte)obj2) // 修改为 if(static_cast<const Carte&>(obj1) == static_cast<const Carte&>(obj2))
验证效果
修改后,调用Compare时会根据对象实际类型执行对应子类的比较逻辑,正确区分不同子类的对象是否相等。
内容的提问来源于stack exchange,提问作者Theo
相关产品推荐
相关产品推荐

