使用具有抽象基类指针的映射并调用派生类函数
Using a map that has a abstract base class pointer and calling a derived class function
我在网上搜索过,找不到任何解决我问题的方法,希望你能帮忙。
因此,我构建了一个抽象基类,并有两个派生类来表示不同的实验。(其中一个实际上是我基类的派生类)我在一个单独的头文件中制作了一个映射,以存储不同类型的实验。
//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中,我构建了不同类型的实验,我想打印它们。每个实验类都有不同的打印函数实现,该函数覆盖基类中的打印函数,如:
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!
}
您正在保存一个指向已销毁对象的指针。你可以检查你在地图上的地址,很可能它们是相同的。你应该把你的实验对象存储在动态存储器中
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>*
。在这里你可以阅读更多关于它的内容。也可以考虑使用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
- 如果整个应用程序是虚拟映射的,为什么 new 会进行系统调用?
- C++ 防止在映射中放置()时调用析构函数
- 由并发无序映射查找线程调用的函数是否安全?
- 计算一个单词在映射中出现的次数 - 使用 transform() - 调用不匹配
- 重载调用是不明确的:一对内联映射作为构造函数参数
- 使用函数指针映射时的 C++ 调用函数
- C ++尝试访问映射中的元素会给我一个不匹配的函数调用错误
- C++不能从映射调用 lambda 表达式
- C++调用存储在映射结构中的函数指针
- C++ 使用映射中的参数调用函数
- Winapi:是否需要在可执行内存映射的文件上调用FlushInstructionCache
- 如何在下一次函数调用中使用 STL 映射擦除从最后一个位置
- 如何调用存储在映射中的函子
- 调用存储在映射中的模板化std::函数
- C /C#Interop中的内存映射和P/调用性能
- 如何使用 JavaCpp 将函数调用从 c++ 映射到 Java?
- 将类插入 STL 映射时出现"调用没有匹配函数"错误
- 将函子存储在 stl 映射中并调用它们
- 从指针映射调用函数,指向具有可变数量参数的函数
- 使用派生类的向量映射调用其类的函数