创建第三个对象的工作原理,创建第四个对象崩溃程序(c ++)

时间:2013-09-30 04:59:08

标签: c++ oop object

新手/学生程序员,试图弄清楚这里发生了什么。

我有一个'leg'类和'route'类,其中路由是通过将一个早期的路由对象添加到leg对象来构建的。

路由类有两个构造函数;一个用一条腿创建初始路线,另一条用于使用前一条路线和另一条路线建立后续路线。

一切似乎都适合

  • 使用仅腿构造函数

  • 创建第一个路径
  • 使用leg + route构造函数创建第二个路径

  • 使用leg + route构造函数创建第三个路径

但是,如果我尝试以相同的方式创建第四个路径,我创建第二个和第三个,程序将编译,但程序到达第一个路径对象时会崩溃。

代码如下:

/////////////////////////////
/* includes and namespaces */
/////////////////////////////


#include <iostream>
using std::cin;
using std::cout;
using std::endl;

#include <ostream>
using std::ostream;


#include <cstdlib> // use for: atof(), atoi()




///////////////////////
/* const definitions */
///////////////////////




////////////////////////
/* struct definitions */
////////////////////////


///////////////////////
/* class definitions */
///////////////////////

class Route;

class Leg
{
  private:
    const char* const startCity;
    const char* const endCity;
    const int length;


  public: 
    Leg( const char* const, const char* const, const int );
    friend void printLeg( ostream&, const Leg&);


    friend void printRoute( ostream&, const Route& );

};

class Route
{
  private:
    const Leg** legsPtrArray;
    const int totalLegs;


  public:
    Route( const Leg& );
    Route( const Route&, const Leg& );
    Route( const Route&);  
    ~Route();

    friend void printRoute( ostream&, const Route& );



};


/////////////////////////
/* function prototypes */
/////////////////////////




///////////////////
/* main function */
///////////////////

int main()
{


  Leg Leg1( "San Francisco", "Reno", 218 );

  Leg Leg2( "Reno", "Salt Lake City", 518 );

  Leg Leg3( "Salt Lake City", "Kansas City", 604 );

  Leg Leg4( "Kansas City", "Indianapolis", 482 );

  Leg Leg5( "indianapolis", "NYC", 709 );

  cout << "Legs loaded, press [enter] to print each leg" << endl;

  cin.get();

  cout << "Leg 1: " << endl << endl;
  printLeg( cout, Leg1 );
  cin.get();

  cout << "Leg 2: " << endl << endl;
  printLeg( cout, Leg2 );
  cin.get();

  cout << "Leg 3: " << endl << endl;
  printLeg( cout, Leg3 );
  cin.get();  

  cout << "Leg 4: " << endl << endl;
  printLeg( cout, Leg4 );
  cin.get();  

  cout << "Leg 5: " << endl << endl;
  printLeg( cout, Leg5 );
  cin.get();

  cout << "Building complete route: " << endl << endl;

  Route Route1( Leg1 );

  Route Route2( Route1, Leg2 );

  Route Route3( Route2, Leg3 );

  cout << "Route built! Press [enter] to print" << endl << endl;

  cin.get();

  printRoute( cout, Route3);

  /*

  Route Route4( Route3, Leg4 );

  cout << "Route built! Press [enter] to print" << endl << endl;

  cin.get();

  printRoute( cout, Route4);

  */

  /*

  Route Route5( Route4, Leg5 );

  cout << "Route built! Press [enter] to print" << endl << endl;

  cin.get();

  printRoute( cout, Route5);

  */

  cout << endl;

  cout << "Press [enter] to quit " << endl;

  cin.get();


}

//////////////////////////
/* function definitions */
//////////////////////////


Leg::Leg( const char* const startCityToLoad, const char* const endCityToLoad, const int lengthToLoad )
 : startCity( startCityToLoad ), endCity( endCityToLoad ), length( lengthToLoad )
{

}

void printLeg( ostream& out, const Leg& legToPrint )
{
  out << "Leg start city: " << legToPrint.startCity << endl;
  out << "Leg end city: " << legToPrint.endCity << endl;
  out << "Leg length: " << legToPrint.length << " miles" << endl;

}

Route::Route( const Leg& legToAdd)
: totalLegs( 1 ), legsPtrArray ( new const Leg*[totalLegs] )
{

  legsPtrArray[0] = &legToAdd;

}

Route::Route( const Route& subRoute, const Leg& legToAdd)
: totalLegs( subRoute.totalLegs + 1 ), legsPtrArray ( new const Leg*[totalLegs] )
{

  for (int i = 0; i < subRoute.totalLegs ; i++)
  {
    legsPtrArray[i] = subRoute.legsPtrArray[i];

  }

  legsPtrArray[subRoute.totalLegs] = &legToAdd;

}

Route::Route( const Route& routeCopy )
: totalLegs( routeCopy.totalLegs ), legsPtrArray ( routeCopy.legsPtrArray )
{

}

Route::~Route()
{
  delete[] legsPtrArray;
}

void printRoute( ostream& out, const Route& routeToPrint )
{

  out << "Route: from " 
    << routeToPrint.legsPtrArray[0]->startCity 
    << " to "
    << routeToPrint.legsPtrArray[0]->endCity 
  ; 

  for (int i = 1; i < routeToPrint.totalLegs; i++)
  {
    out 
      << " to " 
      << routeToPrint.legsPtrArray[i]->endCity;
  }

  out << endl << endl;



  int routeLength = 0;

  for (int i = 0; i < routeToPrint.totalLegs; i++)
  {
    routeLength = 
      routeLength + routeToPrint.legsPtrArray[i]->length;

  }

    out << "Route Length: " << routeLength << " miles" << endl;

}

按原样,这个编译并运行良好。

如果我删除了

周围的评论
  /*

  Route Route4( Route3, Leg4 );

  cout << "Route built! Press [enter] to print" << endl << endl;

  cin.get();

  printRoute( cout, Route4);

  */

程序成功创建了腿,然后在到达第一条路径时崩溃。

我知道我必须做......指针有问题,但我无法弄清楚是什么以及为什么会导致程序以这种特殊方式崩溃。

如果有人比我更有洞察力,我会很感激帮助。

1 个答案:

答案 0 :(得分:0)

您的问题是构建初始值设定项列表元素的顺序。

尝试在Route类中交换成员声明。它应该是这样的:

class Route
{
  private:
  const int totalLegs; // totalLegs comes first
  const Leg** legsPtrArray; // array comes next

我刚刚验证了它在我的系统上运行。

要了解原因,请查看here

编辑:添加我得到的输出:

Leg 5:

Leg start city: indianapolis
Leg end city: NYC
Leg length: 709 miles

Building complete route:

Route built! Press [enter] to print


Route: from San Francisco to Reno to Salt Lake City to Kansas City

Route Length: 1340 miles
Route built! Press [enter] to print


Route: from San Francisco to Reno to Salt Lake City to Kansas City to Indianapolis

Route Length: 1822 miles

Press [enter] to quit

编辑:解释这个怪癖......

任何C ++类只能有一个析构函数,但有几个构造函数。

现在,析构函数的一个要求是它必须以与构造相反的顺序销毁对象的字段(原始字段或其他字段)。

这意味着必须只是一个明确定义的构造顺序。这意味着,字段的构造顺序不能取决于它们在构造函数初始化列表中的指定顺序;因为一个类可以有几个构造函数,每个构造函数都在初始化列表中指定它们自己的字段顺序。因此编译器使用类定义中字段的顺序作为初始化顺序,而不是初始化列表中的顺序。

在你的程序中,基本上数组legsPtrArray在其长度totalLegs之前被初始化(因为它们在程序中被指定的顺序)。未定义的totalLegs值将是一些垃圾,导致数组的初始化失败。