在cout打印物体吸气剂后崩溃

时间:2015-04-05 09:56:43

标签: c++ class inheritance std destructor

基本上我的代码崩溃了,我无法找到原因,我使用了Code :: Blocks调试器,但对我没用。它打印出属性的正确数据后崩溃[4]。我知道这不是最好的方法,但它适用于我需要展示多种方式的类。我的问题是在显示“River Kwai Restaurant”之后它崩溃并且无法弄清楚原因。

const int MAX_PROPERTIES = 5;

int main(void) {
   Property properties[MAX_PROPERTIES];
   Rentals tempRent;

  tempRent = Rentals();
   tempRent.setBond(10000);
   tempRent.setMonthlyRent(700);

   tempRent.setOwner("River Kwai Restaurant");
   tempRent.setAddress("3 Bishopton Road");
   tempRent.setSuburb("Footscray");
   tempRent.setPostcode(5000);

   properties[4] = tempRent;
   tempRent.~Rentals();

   cout << properties[4].getOwner() << endl;


   return 0;
}

Property::Property(){
   owner = "NULL";
   address = "NULL";
   suburb = "NULL";
   postcode = 0;
}

Property::Property(string theOwner, string theAddress,
                   string theSuburb, int thepostCode):
                     owner(theOwner), address(theAddress),
                     suburb(theSuburb), postcode(thepostCode){}

Property::~Property() {}

Rentals::Rentals(string theOwner, string theAddress, string theSuburb,
                  int thePostCode, double theBond, double theMonthlyRent):
                  Property(theOwner, theAddress, theSuburb, thePostCode),
                  bond(theBond), monthlyRent(theMonthlyRent){}

Rentals::Rentals() : Property() {
   owner = "NULL";
   address = "NULL";
   suburb = "NULL";
   postcode = 0;
   bond = 0;
   monthlyRent = 0;
}

Rentals::~Rentals() {}

注意:删除析构函数会修复它,但我想知道为什么?析构函数应该不会影响属性[4],因为它已经初始化了吗?

这是相关的代码,但如果需要,我会在下面发布整个代码/头文件。

#include "property_a.h"
#include "rentals.h"
#include "commercial.h"
#include "sales.h"

const int MAX_PROPERTIES = 5;

int main(void) {
   Property properties[MAX_PROPERTIES];
   Rentals tempRent;

   properties[0] = Commercial("Notting Hill McDonalds",
                              "4 Gardiner Road", "Notting Hill", 5000,
                              "Li3000");

   properties[1] = Rentals("Janet Dalgleish", "30 Firhill Court",
                           "Mary Hill", 4000, 500.00, 300.00);

   properties[2] = Sales("Robert Burns", "3 Ayr Court", "Irvine", 4000,
                         "10/10/2015", 700000);

   properties[3] = Property();
   properties[3] = properties[0];


   tempRent = Rentals();
   tempRent.setBond(10000);
   tempRent.setMonthlyRent(700);

   tempRent.setOwner("River Kwai Restaurant");
   tempRent.setAddress("3 Bishopton Road");
   tempRent.setSuburb("Footscray");
   tempRent.setPostcode(5000);

   properties[4] = tempRent;

   cout << properties[4].getOwner() << endl;


   return 0;
}

Property::Property(){
   owner = "NULL";
   address = "NULL";
   suburb = "NULL";
   postcode = 0;
}

Property::Property(string theOwner, string theAddress,
                   string theSuburb, int thepostCode):
                     owner(theOwner), address(theAddress),
                     suburb(theSuburb), postcode(thepostCode){}

Property::~Property() {}

Commercial::Commercial() : Property() {
   owner = "NULL";
   address = "NULL";
   suburb = "NULL";
   postcode = 0;
   license = "NULL";
}

Commercial::Commercial(string theOwner, string theAddress,
                        string theSuburb, int thepostCode,
                        string theLicense): Property(theOwner, theAddress,
                        theSuburb, thepostCode), license(theLicense) {}

Commercial::~Commercial() {}

Rentals::Rentals(string theOwner, string theAddress, string theSuburb,
                  int thePostCode, double theBond, double theMonthlyRent):
                  Property(theOwner, theAddress, theSuburb, thePostCode),
                  bond(theBond), monthlyRent(theMonthlyRent){}

Rentals::Rentals() : Property() {
   owner = "NULL";
   address = "NULL";
   suburb = "NULL";
   postcode = 0;
   bond = 0;
   monthlyRent = 0;
}

Rentals::~Rentals() {}

Sales::Sales(string theOwner, string theAddress, string theSuburb,
               int thepostCode, string theAuctionDate, double thePrice):
               Property(theOwner, theAddress, theSuburb, thepostCode),
               auctionDate(theAuctionDate), price(thePrice) {}

Sales::Sales() : Property() {
   owner = "NULL";
   address = "NULL";
   suburb = "NULL";
   postcode = 0;
   auctionDate = "NULL";
   price = 0;
}

Sales::~Sales() {}

属性标题

#ifndef __PROPERTY_A_H__
#define __PROPERTY_A_H__


/*TODO  REQUIRED HEADER FILES AND NAMESPACES*/
#include <string>
#include "utility1.h"


class Property
{
protected:
  string owner;
  string address;
  string suburb;
  int postcode;

public:
  Property();
  Property(string theOwner, string theAddress, string theSuburb, int thepostCode);
  virtual ~Property();

  string getOwner() const {return owner;};   //Note the use of const
  string getAddress() const {return address;};
  string getSuburb() const {return suburb;};
  int getPostcode() const {return postcode;};

  void setOwner(string newOwner) {owner = newOwner;};
  void setAddress(string newAddress) {address = newAddress;};
  void setSuburb( string  newSuburb) {suburb = newSuburb;};
  void setPostcode(int  newPostcode) {postcode = newPostcode;};
};
#endif

租赁标题

#ifndef __RENTALS_H__
#define __RENTALS_H__


#include "property_a.h"

class Rentals : public Property
{
protected:
  double bond;
  double monthlyRent;

public:
  Rentals();
  Rentals(string theOwner, string theAddress, string theSuburb,
              int thepostCode, double theBond, double theMonthlyRent);
   ~Rentals() ;

  double getBond() const {return bond;};   //Note the use of const

  void setBond(double theBond) {bond = theBond;};

  double getMonthlyRent() const {return monthlyRent;};   //Note the use of const

  void setMonthlyRent(double theMonthlyRent) {monthlyRent = theMonthlyRent;};


};

#endif

1 个答案:

答案 0 :(得分:1)

另一位评论者建议您查找object slicing.这确实描述了这个问题,但您可以通过在代码中添加一些调试语句来更具体地看到它:

std::cout << "Size of properties: " << sizeof(properties) << std::endl;
std::cout << "Size of properties[4]: " << sizeof(properties[4]) <<std::endl;
std::cout << "Size of tmpRent: "<< sizeof(tempRent) <<std::endl;

输出如下:

Size of properties: 440
Size of properties[4]: 88
Size of tmpRent: 104

看起来一个属性元素不足以容纳子类的元素......发生了什么?

当您声明Properties properties[5]时,您声明了一个Properties类型的对象数组,它会分配一个连续的内存块。您可以通过打印地址来实际看到:

std::cout << "Start of properties: " << &properties <<std::endl;
std::cout << "Address of properties[0]: " << &properties[0] << std::endl;
std::cout << "Address of properties[1]: " << &properties[1] << std::endl;
std::cout << "Address of properties[2]: " << &properties[2] << std::endl;
std::cout << "Address of properties[3]: " << &properties[3] << std::endl;
std::cout << "Address of properties[4]: " << &properties[4] << std::endl; 

在我的机器上,我得到:

Start of properties: 0x7fff5a4c6070
Address of properties[0]: 0x7fff5a4c6070
Address of properties[1]: 0x7fff5a4c60c8
Address of properties[2]: 0x7fff5a4c6120
Address of properties[3]: 0x7fff5a4c6178
Address of properties[4]: 0x7fff5a4c61d0

这些是大数字,但您可以看到数组中每个元素的地址增加了0x58或88个字节。当您分配到属性[4]时,C ++将属性[4]视为指针,并将104个字节复制到它指向的位置。赋值属性[4] = tempRent等同于memcpy(&tempRent, &properties[4], 104)。 C ++只是假设你有足够的内存来保存对象(104字节)。但是在内存块结束之前只剩下88个字节。您的任务将覆盖数组的末尾并破坏下一段内存。该程序可能随时崩溃,它可能显示损坏的数据,或者它似乎工作得很好(就像我在Mac上运行它时一样。)