Problem casting derived class pointer to base class pointer

Dear All,

I have basically the following situation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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.

Could you please tell me what am I doing wrong?

Cheers,
Little
pDerBox is not a pointer.
on line 8: cDerivedBox *pDerBox = new cDerivedBox; // Note that *
My bad: transcription error. The code should look like

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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;
}
Please post real code.
The code you showed shall not be compiled because the derived class has no access to private members of the base class.
For example this statement

pDerbOX->name = "Big Box";

is invalid because name is a private data member of the base class.
Last edited on
Here is a minimum working example that reproduces the problem, straight from VS 2005:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* 
	Main: PLAYING WITH BOXES
*/

#include "stdafx.h"
#include <iostream>
using namespace std;

#include <vector>
#include <string>

#include "Warehouse.h"

int _tmain(int argc, _TCHAR* argv[])
{
	int nRetCode = 0;
	bool ret;
	
	string Name = "test01";

	CWarehouse Warehouse(Name);
	ret = Warehouse.Load();
	if (ret == false){
		fprintf(stderr, "Loading error..\n");
		return 1;
	}
	
	return nRetCode;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//
// Warehouse.h
//

#pragma once
#include <string>
#include <vector>
using namespace std;

#include "BaseBox.h"
#include "DerivedBox.h"

class CWarehouse
{
public:

	CWarehouse(std::string);
	~CWarehouse(void);

	// data box name
	string BoxName;

	// Boxes vectors
	vector<CBaseBox*> BaseBoxes;
	vector<CDerivedBox*> DerivedBoxes;
	
	// number of boxes
	int NumBoxes;

	bool Load();

};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//
// Warehouse.cpp
//

#include <iostream>
using namespace 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++;

	return true;
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
// 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;			
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//
// BaseBox.cpp
//

#include "BaseBox.h"

CBaseBox::CBaseBox(void)
{
	Capacity = 0;
	Weight = 0.0;

    NumLids = 0;
}

CBaseBox::~CBaseBox(void){}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//
// DerivedBox.h
//

#pragma once
#include "BaseBox.h"
#include <string>

class CDerivedBox : public CBaseBox
{
public:
	CDerivedBox(void);
	~CDerivedBox(void);

	std::string color;
	double thickness;
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
//
// DerivedBox.cpp
//

#include "DerivedBox.h"

CDerivedBox::CDerivedBox(void): CBaseBox()
{
	thickness = 0;
}

CDerivedBox::~CDerivedBox(void){}


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;
)
Last edited on
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.
Thank you very much guys, you nailed the problem!

Cheers,
Little
Topic archived. No new replies allowed.