调用虚函数 - 分段错误

时间:2016-10-09 06:38:32

标签: c++ runtime-error virtual

代码的工作方式是有一个名为“Module”的基本纯虚拟类,其子类为“Living”,“Manufacturing”和“PowerGen”,它使用了一些虚函数。在主驱动程序文件中,我成功地从文件中读取模块列表并将它们存储在模块指针的向量中。当我想使用虚拟显示功能来显示矢量元素的模块细节时,就会出现问题。我遇到了分段错误。任何帮助将不胜感激!

Class Module
{
public:
   Module() = default;
   explicit Module(const string& purpose, const string& id)
   {
      this->purpose = purpose;
      this->id = id;
   }
   explicit Module(const string& purpose) { this->purpose = purpose; }
   virtual ~Module() { }

   virtual void setCrew( ) = 0;
   virtual void display( ) const = 0;
   void addCrew(const string& name)
   {
      crew_list.push_back(Crew(name));
      ++number_of_crew;
   }
   void setPowerReq(double power) { this->power = power; }
   void setMaxCrew(int max_crew) { this->max_crew = max_crew; }

   string getPurpose( ) { return purpose; }
   string getId( ) { return id; }
   int getNumberOfCrew( ) { return number_of_crew; }
   int getMaxCrew( ) { return max_crew; }
   double getPower( ) { return power; }

   friend ostream& operator << ( ostream& os, const Module& m );
   friend ofstream& operator << ( ofstream& os, const Module& m );
   friend ifstream& operator >> ( ifstream& is, Module& m );

private:
   string purpose = "unknown";
   string id = "unknown";
   int number_of_crew = 0;
   int max_crew = 0;
   double power = 0;
   vector<Crew> crew_list;
}; 


 class Living : public Module
{
public :

   Living( ) = default;
   explicit Living(const string& purpose);
   Living(int meals, const string& id);
   void setCrew( )
   {
      setMaxCrew( floor(meals / 3) );
      setPowerReq( meals * 1.4 );
   }
   void display( ) const
   {
      cout << *this;
   }

   friend ofstream& operator << ( ofstream& os, const Living& l );
   friend ifstream& operator >> ( ifstream& is, Living& l );

private :
   int meals = 0;
   static string type;
};

class Manufacturing : public Module
{
public:
   Manufacturing( ) = default;
   Manufacturing( const string& product, int quantity, const string& id );
   explicit Manufacturing( const string& purpose );
   void setCrew( )
   {
      setPowerReq( quantity * 6 );
      setMaxCrew( maxCrew );
   }
   void display( ) const
   {
      cout << *this;
   }

   friend ofstream& operator << ( ofstream& os, const Manufacturing& m );
   friend ifstream& operator >> ( ifstream& is, Manufacturing& m );

private:
   static string type;
   string product = "unknown";
   static int maxCrew;
   int quantity = 0;
};

class PowerGen : public Module
{
public:
   PowerGen() = default;
   PowerGen( int number_of_generators, const string& id );
   explicit PowerGen( const string& purpose );
   void setCrew( )
   {
      setMaxCrew(0);
      setPowerReq( -(number_of_generators * 7) );
   }
   void display( ) const
   {
      cout << *this;
   }

   friend ofstream& operator << ( ofstream& os, const PowerGen& p );
   friend ifstream& operator >> ( ifstream& is, PowerGen& p );

private:
   static string type;
   const int max_generators = 8;
   int number_of_generators = 0;
};

与主驱动程序文件相关的部分,当调用时会导致分段错误:

if( cityVector.size() > 0 )
   {
      cout << "\nHere is the complete City" << endl;
      for ( auto iter : cityVector )
      {
         iter->display( );
         cout << endl << endl;
      }
   } else {
      cout << "\nThere are no Modules in the City" << endl;
   }

这是我从文件中加载数据的方式,其中VMOD = vector:

void load( VMOD & cityVector )
{
   string filename;
   cout << "Please enter a filename >> ";
   getline( cin, filename );
   ifstream fin;
   fin.open(filename);
   if (!fin.fail())
   {
      while ( !fin.eof() )
      {
         string purpose;
         getline( fin, purpose );
         if ( purpose == "Living" )
         {
            Living object(purpose);
            loadObject( cityVector, object, fin );
          } else if ( purpose == "Manufacturing" )
         {
            Manufacturing object(purpose);
            loadObject( cityVector, object, fin );
         } else if ( purpose == "Power Generation" )
         {
            PowerGen object(purpose);
            loadObject( cityVector, object, fin );
         } else {

         }
      }
      cout << "The city has " << cityVector.size() << " modules!" << endl;
   } else {
      cout << "File does not exist... " << endl;
   }
   fin.close();
}

template<typename T>
void loadObject( VMOD & cityVector, T object, ifstream& fin )
{
   fin >> object;
   Module* mptr;
   mptr = &object;
   cityVector.push_back(mptr);
}

文件看起来像这样:

Living
L1
5
21
2
First Person
Fourth Person
15
Manufacturing
M1
10
12
4
Second Person
Third Person
Fifth Person
Sixth Person
C++ ness
2
Power Generation
P1
0
-14
0
2

1 个答案:

答案 0 :(得分:0)

你有一个悬空指针问题。

template<typename T>
void loadObject( VMOD & cityVector, T object, ifstream& fin )
{
   // object is a function local object
   // since it is passed by value.
   fin >> object;
   Module* mptr;

   // This is a pointer to a local object.
   // It is invalid when the function returns.
   mptr = &object;

   // Storing a pointer that will be a dangling pointer as soon
   // the function returns.
   cityVector.push_back(mptr);
}

您需要为已还原的对象使用动态分配的内存,并将其保存在cityVector

完成使用后,您需要确保释放内存。

template<typename T>
void loadObject(VMOD& cityVector, ifstream& fin )
{
   T* objectPtr = new T;
   fin >> *objectPtr;
   cityVector.push_back(objectPtr);
}

并使用以下语法调用它:

loadObject<LivingObject>(cityVector, fin);
相关问题