You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 07:19:55