我有这些课程:
class Base
{
private:
string name;
public:
void setName(string n);
string getName();
void toString();
}
和两个派生自此的类:
class DerivedA : public Base
{
private:
int width;
public:
void setWidth(int w);
int getWidth();
}
和
class DerivedB : public Base
{
private:
int height;
public:
void setHeight(int h);
int getHeight();
}
现在回答我的问题。我的主要看起来像这样:
int main()
{
Base* b;
string line;
... file loading ...
while(...)
{
s = cin.getline(file,10);
if(s == "w")
{
b = new DerivedA();
}
else if(s == "h")
{
b = new DerivedB();
}
while(...)
{
b->toString();
}
}
return 0;
}
这总是会终止我的应用。我发现b->toString();
部分可能是问题的根源,因为范围不同。但无论如何,有什么方法可以做到这一点? (我遗漏了无聊和无关的代码部分。)
答案 0 :(得分:2)
Base
应该有一个虚拟析构函数,并且您要覆盖的每个函数都应该声明为virtual
。此外,您的main
功能需要进行一些修改:
int main()
{
Base* b = nullptr; // initialize your pointer
string line;
// ... file loading ...
while(std::getline(file, line)) // this should be your while loop for your file parsing
{
//s = cin.getline(file,10); // why??? you appear to be trying to pass your ifstream object into cin's istream::getline method ... this won't even compile!
// I'm assuming s is a std::string, and you pull it out of the line variable at some point ...
if(s == "w")
{
if (b != nullptr) // properly free your memory
{
delete b;
b = nullptr;
}
b = new DerivedA();
}
else if(s == "h")
{
if (b != nullptr) // properly free your memory
{
delete b;
b = nullptr;
}
b = new DerivedB();
}
while(...)
{
if (b != nullptr) // make sure b is valid!
{
b->toString();
}
}
}
return 0;
}
这总是会终止我的应用。我发现了b-> toString(); 部分可能是问题的根源,因为范围不同。 但无论如何,有什么方法可以做到这一点?
首先,您发布的内容(可能)甚至不会编译。 cin.getline
将尝试从标准输入中读取。您的评论表明您正在加载文件,因此(假设file
是std::ifstream
个实例,cin.getline(file, 10)
正在尝试调用不存在的函数std::istream::getline(std::istream&, int)
。{ {1}}执行您想要在此处执行的操作。此外,即使您尝试阅读标准输入,也应该是std::getline
,而不是std::getline(std::cin, s)
。
接下来,下一个区域是你的内存泄漏。这些很容易解决,1)在声明时初始化cin.getline(file, 10)
,2)在泄漏内存之前正确b
。空检查不是完全必要的(初始化delete
),因为b
无论如何都会检查delete
,但我在那里写了它们来说明一点:你应该管理你的记忆得恰到好处!
接下来,你的if-else if条件有可能不做任何事情(也就是说,NULL
会更糟或没有初始化,或者最好是b
。如果您不想为非“s”/“h”输入做任何事情,那很好,但是必须执行以下项目(无论如何都应该这样做)。
最后,可能导致崩溃的问题不是在尝试使用NULL
之前检查b
是否有效:b->toString();
。如果b
无效或为null,则表示您正在调用未定义的行为。你的程序可能会崩溃,打电话给你的祖母,或者为总统订一份披萨......所有这些都是有效的选择,而不是你真正打算做的。