int main(int argc char* argv[])
{
// vectors that will contain pointers to BaseBox objects
vector<cBaseBox*> BaseVector;
// pointer to cDerivedBox object
cDerivedBox pDerBox = new cDerivedBox;
// initialization
pDerbOX->name = "Big Box";
pDerBox->weight = 10;
pDerBox->height = 10;
pDerBox->color = "white";
pDerBox->thickness = 0.5;
// pointer to a BaseBox object
cBaseBox* pBasBox;
// casting of derived class pointer to base class pointer
pBasBox = dynamic_cast<cBaseBox*>(pDerBox);
// include pointer to base object in vector
BaseVector.push_back(pBasBox);
return 0;
}
class cBaseBox
{
private:
string name;
double weight;
double height;
}
class cDerivedBox : public cBaseBox
{
private:
string color;
double thickness;
}
I am getting the following runtime error:
Unhandled exception at 0x777e15de in Boxes.exe: 0xC0000005: Access violation reading location 0xfeeefee2.
I have pinpointed the problem to the line
BaseVector.push_back(pBasBox);
So in essence there seems to be a problem when casting my derived class pointer to a base class pointer. While debugging I looked at the base pointer after casting, and my guess is that it would have been stripped of those fields that correspond to the derived class; however that is not happening.
//
// Warehouse.cpp
//
#include <iostream>
usingnamespace std;
#include <string>
#include "Warehouse.h"
#include "BaseBox.h"
#include "DerivedBox.h"
// constructor
CWarehouse::CWarehouse(std::string name)
: NumBoxes(0)
{
BoxName = name;
BaseBoxes.clear();
DerivedBoxes.clear();
}
// destructor
CWarehouse::~CWarehouse(void)
{
for(vector<CBaseBox*>::iterator it = BaseBoxes.begin(); it != BaseBoxes.end(); ++it)
delete (*it);
for(vector<CDerivedBox*>::iterator it = DerivedBoxes.begin(); it != DerivedBoxes.end(); ++it)
delete (*it);
BaseBoxes.clear();
DerivedBoxes.clear();
}
bool CWarehouse::Load()
{
//////////////////////////////////////
/////////// load box data ///////////
//////////////////////////////////////
// pDerBox: pointer to derived box
CDerivedBox* pDerBox = new CDerivedBox;
// reads box name
pDerBox->Name = "New Box";
// inserts pointer to derived class in list of derived boxes
DerivedBoxes.push_back(pDerBox);
// creates pointer to base class
CBaseBox* pBasBox = new CBaseBox;
// casts derived class pointer to base class pointer
pBasBox = dynamic_cast<CBaseBox*>(pDerBox);
// inserts pointer to base class in list of base boxes
BaseBoxes.push_back(pBasBox); // THIS LINE IS CAUSING THE PROBLEM
// increases number of load devices
NumBoxes++;
returntrue;
};
//
// BaseBox.h
//
#pragma once
#include <string>
class CBaseBox
{
public:
CBaseBox(void);
~CBaseBox(void);
// box name
std::string Name;
// lid information
int NumLids;
double Capacity;
double Weight;
};
There are several memory management errors in this program:
1) A destructor of a base class must be either public and virtual or protected and non-virtual:
replace ~CBaseBox(void);
with virtual ~CBaseBox(void);
2) Do not delete objects twice
At minimum, replace pBasBox = dynamic_cast<CBaseBox*>(pDerBox); // this pointer points at the same object as pDerBox
with pBasBox = dynamic_cast<CBaseBox*>(new CDerivedBox); // this is a different Derived Box
(your CWarehouse attempts to call delete on every pointer it holds, and you gave it both pointers)
3) Don't leak memory:
replace CBaseBox* pBasBox = new CBaseBox;
with CBaseBox* pBasBox;
(P.S dynamic_cast is not necessary in this case, you can just assign directly: pBasBox = new CDerivedBox;
)
The code you showed shall not crash in the statement you marked
BaseBoxes.push_back(pBasBox); // THIS LINE IS CAUSING THE PROBLEM
in spite of the memory leak produced by the statements
CBaseBox* pBasBox = new CBaseBox;
pBasBox = dynamic_cast<CBaseBox*>(pDerBox);
It is the destructor that leads to the crash
1 2 3 4 5 6 7 8 9 10 11
CWarehouse::~CWarehouse(void)
{
for(vector<CBaseBox*>::iterator it = BaseBoxes.begin(); it != BaseBoxes.end(); ++it)
delete (*it);
for(vector<CDerivedBox*>::iterator it = DerivedBoxes.begin(); it != DerivedBoxes.end(); ++it)
delete (*it);
BaseBoxes.clear();
DerivedBoxes.clear();
}
You are trying to delete the same pointer twice. The first time in vector<CBaseBox *> and the second time in vector<CDerivedBox *>.
As Cubbi said already there is no need to use dynamic_cast. And you shall declare the destructor as virtual.