代码之家  ›  专栏  ›  技术社区  ›  AliS

使用具有抽象基类指针的映射并调用派生类函数

  •  0
  • AliS  · 技术社区  · 8 年前

    我已经在网上搜索过,找不到任何解决我问题的方法,希望你能帮我。

    因此,我构建了一个抽象基类,并有两个派生类来表示不同的实验。(一个实际上是我的基类的派生类)我在一个单独的头文件中创建了这样的映射,以存储不同类型的实验。

    //Map class template to store name of experiment and the experiment within a project
    typedef map <string, baseData <double>*> ExpContainer;
    
    void search(string searchName, ExpContainer exps) {
        ExpContainer::iterator Iter;
        Iter = exps.find(searchName); //finds the entry corresponding to searchName and returns the iterator
        if (Iter != exps.end()) { //need this as if entry is not found, the return will be end iter.
            cout << "Found the experiment " << Iter->first << "." << endl;
            Iter->second->print();
        }
        else {
    
            cout << "Sorry, experiment " << searchName << " is not found" << endl;
        }
    
    }
    

    对于每个实验类型,print()函数都是不同的,我知道存在一个称为切片的问题,所以我已经确保print()在基类中是虚拟的。这是我的基本类:

    namespace mynmsp {
    
    //base class of data can be measurements or errors
    template < class T> class baseData { 
    
    public:
        virtual void print() =0;
        virtual ~baseData() {
            cout << "Destructor called for the base class." << endl;
        }
    };
    }
    

    然后在我的主要。我构建了不同类型的实验,我想打印出来。每个实验类都有不同的打印函数实现,该函数覆盖了基类中的打印函数,如:

    void print(){ //do something }; 
    

    在我的主要。cpp I将映射定义为:

    ExpContainer project;
    

    在构建完每个实验之后,我向用户询问实验的名称(expName),并将其插入到项目中,如下所示:

    project[expName] =  &expC;
    

    我认为插入是好的,因为我测试了项目的大小,它是正确的。 但是,当我的搜索函数按如下方式调用时,发生了运行时错误:

    search(name, project);
    

    我不知道切片还是指针有问题? 我试图在每个派生类中使print()成为一个虚拟函数,但这似乎也不起作用。

    很抱歉问了这么长的问题,请帮帮我!

    编辑:我在do-while循环中构造了实验,而在外部声明了项目。整个代码很长,但其基本内容如下:

    string repeatstr; //user input whether to repeat do while loop or not
    bool repeat = true; //condition for staying inside do while loop
    ExpContainer project; //declared project to store experiments
    
    do {
        string expName;
        string ans1; //character to store user input
        cout << "What is the name of your experiment? " << endl;
        cin >> expName;
        cout << "Is this a experiment C ? (y/n)" << endl;
        cin >> ans1; 
           if(ans1 =="y"){ 
               //call the constructor for expC
               project[expName] = &expC;
            }else {
               //call the constructor for expB 
              project[expName] = &expB;
            }
    
        cout << "Do you want to enter another experiment?  (y/n)" << endl;
        cin >> repeatstr;
        if (repeatstr == "n") { repeat = false;  }
    
    }while (repeat); //loop over this do-while loop while repeat is true
    
        cout << "There are " << project.size() << " in this database." << endl;
    
        //to retrieve info from a certain experiment
        string input, name;
        cout << "Would you like to retrieve any experiments (y/n)? " << endl;
        input = EitherInput("y", "n");
        if (input == "y") {
            cout << "Please enter the name of the experiment you want to retrieve: " << endl;
            cin >> name;
            search(name, project); //code breaks down here!
        }
    
    1 回复  |  直到 8 年前
        1
  •  0
  •   Teivaz Nima Soroush    8 年前

    您正在保存指向已销毁对象的指针。你可以检查地图上的地址,很可能它们是相同的。你应该把实验对象存储在动态内存中

    if(ans1 =="y")
    { 
        project[expName] = new expC();
    } // Scope ends here and all variable created in it will be destroyed.
    else 
    {
      project[expName] = new expB();
    } // Scope ends here and all variable created in it will be destroyed.
    

    完成后,您需要致电 delete 以避免内存泄漏。此外,还需要检查映射中的项是否已经存在,否则将丢失指向已分配内存的指针,这将自动导致内存泄漏。

    我建议你使用 std::share_ptr< baseData<double> > 而不是光秃秃的 baseData<double>* . Here 你可以阅读更多关于它的信息。还可以考虑使用typedef以获得更清晰的语法。


    附笔。 功能

    void search(string searchName, ExpContainer exps)
    

    将整个地图复制到其主体。改用常量引用

    void search(string searchName, const ExpContainer& exps)
    

    但是,您还需要将函数print声明为const:

    virtual void print() const = 0;
    

    并使用const修饰符覆盖它:

    virtual void print() const override;
    

    并使用常量迭代器 ExpContainer::const_iterator Iter