我在网上搜索过,无法找到解决问题的方法,希望你能提供帮助。
所以我构建了一个抽象基类,并有两个代表不同实验的派生类。 (一个实际上是我的基类的派生派生类)我在一个单独的头文件中制作了一个地图,以存储不同类型的实验。
//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!
}
答案 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