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

时间:2016-05-15 21:32:07

标签: c++ dictionary inheritance virtual slice

我在网上搜索过,无法找到解决问题的方法,希望你能提供帮助。

所以我构建了一个抽象基类,并有两个代表不同实验的派生类。 (一个实际上是我的基类的派生派生类)我在一个单独的头文件中制作了一个地图,以存储不同类型的实验。

//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;
    }
};
}

然后在我的main.cpp中,我构建了不同类型的实验,我想打印它们。每个实验类都有不同的print函数实现,它覆盖了基类的print函数,如:

void print(){ //do something }; 

在我的main.cpp中,我将地图定义为:

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 个答案:

答案 0 :(得分:0)

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

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以获得更清晰的语法。

P.S。 功能

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