C++ 基于函数参数选择派生类
我有以下课程:C++ 基于函数参数选择派生类,c++,C++,我有以下课程: 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 getWidt
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();
}
及
现在回答我的问题。我的主要观点如下:
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;部分可能是问题的根源,因为范围不同。但不管怎样,有没有办法我该怎么做?我省略了代码中枯燥和不相关的部分。Base应该有一个虚拟析构函数,并且您想要重写的每个函数都应该声明为虚拟的。此外,您的主要功能需要进行一些修改:
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将尝试从标准输入读取。您的注释表明您正在加载一个文件,因此假设该文件是std::ifstream实例cin.getlinefile,10将尝试调用一个不存在的函数std::istream::getlinestd::istream&,int。getline执行您在此处似乎想要执行的操作。此外,即使您试图读取标准输入,也应该是std::getlinestd::cin,s,而不是cin.getlinefile,10
接下来,下一个问题是内存泄漏。通过1在声明b时初始化它,2在泄漏内存之前正确地删除它,可以很容易地修复这些问题。对于初始化的b,null检查并不是完全必要的,因为delete无论如何都会检查null,但我在那里写了它们来说明一点:您应该正确地管理内存
接下来,if-else-if条件有可能不执行任何操作,也就是说,b在更坏的情况下是未初始化的,或者在最好的情况下是NULL。如果您不想对非s/h输入执行任何操作,这很好,但是您必须执行以下操作,无论如何您都应该这样做
最后,可能导致崩溃的问题是在尝试使用b之前没有检查b是否有效:b->toString;。如果b无效或为null,则调用未定义的行为。你的程序可能会崩溃,打电话给你的祖母,或者给总统点比萨饼。。。所有选项都是有效的选项,其中没有一个是您真正想要做的。您确定其中一个if语句正在执行吗?如果它们都不执行,b就没有被初始化,这可能是你的问题。这甚至可以编译吗?!由于从未删除过b,因此也在泄漏内存,如果此操作运行一段时间,最终会出现内存不足异常。您的基类需要一个虚拟析构函数。如果您计划重写它,则还应标记为String virtual。我认为这不应成为一个错误answer@khajvah想详细说明吗?这不是他的问题的答案。您已经提供了一些有用的信息,但这并不是为什么它不起作用的答案?或者我该怎么做?。这将编译并运行,但很可能不会像OP预期的那样工作,因为您只是防止了它失败。公平地说,用OP提供的信息回答是不可能的,但是…他的问题的答案仍然是变化:主要是,在他尝试调用b->toString之前的null检查,当他使用null或未初始化的指针调用它时,这可能会导致程序崩溃。事实上,有一部分不会像他写的那样编译,我在编辑中提到过。@khajvah在我详细介绍的时候看到了我的编辑。
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;
}