根据函数参数选择派生类

时间:2013-10-30 20:30:30

标签: 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 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();部分可能是问题的根源,因为范围不同。但无论如何,有什么方法可以做到这一点? (我遗漏了无聊和无关的代码部分。)

1 个答案:

答案 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将尝试从标准输入中读取。您的评论表明您正在加载文件,因此(假设filestd::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,则表示您正在调用未定义的行为。你的程序可能会崩溃,打电话给你的祖母,或者为总统订一份披萨......所有这些都是有效的选择,而不是你真正打算做的。