C++ 创建第三个对象工作,创建第四个对象崩溃程序(c+;+;)
新手/学生程序员,试图找出这里的漏洞 我有一个“leg”类和一个“route”类,其中通过向leg对象添加一个早期的route对象来构建路由 route类有两个构造函数;一个用于使用一条支腿创建初始管线,另一个用于使用前一条管线加上另一条支腿构建后续管线 对我来说,一切似乎都很好C++ 创建第三个对象工作,创建第四个对象崩溃程序(c+;+;),c++,oop,object,C++,Oop,Object,新手/学生程序员,试图找出这里的漏洞 我有一个“leg”类和一个“route”类,其中通过向leg对象添加一个早期的route对象来构建路由 route类有两个构造函数;一个用于使用一条支腿创建初始管线,另一个用于使用前一条管线加上另一条支腿构建后续管线 对我来说,一切似乎都很好 使用leg-only构造函数创建第一条管线 使用leg+route构造函数创建第二条管线 使用leg+route构造函数创建第三条路线 但是,如果我尝试以与创建第二条和第三条路由相同的方式创建第四条路由,程序将编译
- 使用leg-only构造函数创建第一条管线
- 使用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;
}
/////////////////////////////
/*包括和名称空间*/
/////////////////////////////
#包括
使用std::cin;
使用std::cout;
使用std::endl;
#包括
使用std::ostream;
#包括//用于:atof(),atoi()
///////////////////////
/*常量定义*/
///////////////////////
////////////////////////
/*结构定义*/
////////////////////////
///////////////////////
/*类定义*/
///////////////////////
班级路线;
班腿
{
私人:
常量字符*常量起始值;
常量字符*常量结束城市;
常量int长度;
公众:
支腿(常量字符*常量,常量字符*常量,常量整数);
friend void打印腿(ostream&,const Leg&);
friend void打印路径(ostream&,const路径&);
};
班级路线
{
私人:
施工支腿**支腿;
总常数;
公众:
路线(施工支腿和);
路线(施工路线和施工支腿);
路线(常数路线&);
~Route();
friend void打印路径(ostream&,const路径&);
};
/////////////////////////
/*功能原型*/
/////////////////////////
///////////////////
/*主要功能*/
///////////////////
int main()
{
第1段(“旧金山”、“雷诺”,218);
第2段(“雷诺”,“盐湖城”,518);
第3段(“盐湖城”、“堪萨斯城”,604年);
第4段(“堪萨斯城”、“印第安纳波利斯”,482);
Leg5(“印第安纳波利斯”,“纽约”,709);
cout您的问题是初始值设定项列表元素的构造顺序
尝试交换Route类中的成员声明。它应该如下所示:
class Route
{
private:
const int totalLegs; // totalLegs comes first
const Leg** legsPtrArray; // array comes next
我刚刚验证了它在我的系统上工作
要了解原因,请看
编辑:添加我得到的输出:
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++类只能有一个析构函数,但有几个构造函数。
现在,析构函数的一个要求是它必须按照与构造相反的顺序销毁对象的字段(原语或其他)
这意味着必须只有一个定义良好的构造顺序。这意味着字段的构造顺序不能依赖于构造函数初始化列表中指定它们的顺序;因为一个类可以有多个构造函数,每个构造函数在初始化列表中指定自己的字段顺序。因此编译器使用类定义中字段的顺序作为初始化顺序,而不是初始化列表中的顺序
在您的程序中,基本上数组legsptrary
在其长度totalegs
之前就已初始化(因为它们在程序中的指定顺序)。未定义的totalEGS
值将是一些垃圾,这将导致数组初始化失败。它在创建路由
或打印时是否崩溃?不确定它是否与此崩溃有关,但您的路由
复制构造函数不正确。它将浅层复制,导致多次删除(未定义的行为)在析构函数中。Dang,我现在还不明白为什么需要这个,但它确实有效,所以我最好看看它,直到我弄清楚为什么需要它。谢谢!@stellarsjay更新了我的答案,并做了一些解释。希望这能帮上忙。好吧,是的,现在它对我来说是有意义的。我不明白这个函数需要声明根据类的顺序,而不是初始化列表。我猜它对前三个实例有效,因为程序正在查找有效的垃圾值并使用它们。
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