C++ inadvertant pointer manipulation in Interface objects

Hi all,

I have a major problem with my code when attempting to dereference a pointer contained within a structure that is ifself an instance member within an Interface object.

The following code snipit is a simplication of the issue at hand.
First suppose I have a struct, and in the definition of the struct I delcare a coupple of pointers to some class-types.

Next, I define an interface object which has one method and contains a pointer to a the struct as a member attribute.

Next, I define a class type C that conforms to the interface object I. During the constructor call - the member attribute pointer is allocated.And we can print out the memory address of the object A and object B

Next, in some general class an instance of C is created and added to a std::List container object - defined to hold Interface Object I

Finally, in some general class D we attempt to get back the interface Object and dereference it. This is where the issue lies. We use an itterator to get to the Interface object. Using this object we can attempt to get to the stuct (and this works - we can successfully print the value of member _id).
But, when attempting to get the ObjTypeA amd ObjTypeB the pointers have changed. They are no longer pointing to the instances.

Has anyone ever experienced anything like this before? What am I doing wrong?


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
struct MyStruct
{
	int _id;
	ObjTypeA *a
	ObjTypeB *b;
};

class I
{
	public:
		virtual const MyStruct * getMyStruct() = 0;
	
	MyStruct *_data;

};


class C : public I
{
	class C()
	{
		// do stuff
		_data = new MyStruct();
		_data.a = new ObjTypeA();
		_data.b = new ObjTypeB();
		
		
		cout << "id " << hex << _data->_id << endl;
		cout << "object A" << hex << _data->a << endl;
		cout << "object B" << hex << _data->b << endl;
	}
};
	
	
	
... some other user set-up class
{
	...
	C *anObj = new C();
	
	// list is a std::list <I *>
	D->addToList (C)
	D->processList()
}


.... Class D
processList ()
{
	// just grab first item for now 
	std::list <I *>::iterator it = mylist.begin();
	I *obj = *(it);
	
	cout << "id " << hex << obj->_data._id << endl;
	
	// problem is here - the output values do not match
	// expected values
	cout << "object A" << hex << obj->_data.a << endl;
	cout << "object B" << hex << obj->_data.b << endl;
}


Where is _data declared? Is it in I or C? It should be in C, right?

Why are you able to write code like:
 
	cout << "id " << hex << obj->_data._id << endl;


I would expect that you'd need to write:
 
	cout << "id " << hex << obj->getMyStruct()->_id << endl;
Last edited on
The _data is declared in Interface ojbect I
(Originally, I did delcare it in C - but due to the issues, moved it to I described above I moved it to Interface Object I).

Since the structure is declared as public I should be able to access it directly.
Indeed, once again, originally I did make it protected a and required a method such as your to get access. But alass the same issue.


In my poor attempt to illustrate the problem i have slightly over simplified the scenario a wee bit. There is another level of indirection needed to hilight where the problem lies.
The code snipet shows this extra level of indirection - and hence a replacement for Class C.

Notice in class C we can correctly deference all the members of the struct including the pointer members. Also, in class C we are dealing with the Interface Object I and not the original type C, yet by the time we get to class D and deference the Interface Object the addresses of the pointers to reference ObjTypeA and ObjTypeB have changed? The sturture address and contents for the other non-pointer objects remain the same.


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
.... Class C
processList ()
{
	// just grab first item for now 
	std::list <I *>::iterator it = mylist.begin();
	I *obj = *(it);

	// every thing is working as expected at this point	Notice: we are dealing with an
               // interface object at this point and yet we are able to dereference the data correctly

	cout << "id " << hex << obj->_data._id << endl;
	cout << "object A" << hex << obj->_data.a << endl;
	cout << "object B" << hex << obj->_data.b << endl;
	
	D->addObjectToList (I);
	D->processList();
}


.... Class D


addObjectToList (I *obj)
{
	// where m,yList is defined as std::List<I *>
	myList.push_back (obj);
}


processList ()
{
	// just grab first item for now 
	std::list <I *>::iterator it = mylist.begin();
	I *obj = *(it);
	
	cout << "id " << hex << obj->_data._id << endl;
	
	// problem is here - the output values do not match
	// expected values values printed by class C's output
	// something happended that has changed the object pointers, but not
	// the pointer to the struct.
	cout << "object A" << hex << obj->_data.a << endl;
	cout << "object B" << hex << obj->_data.b << endl;
}
The _data is declared in Interface ojbect
You're right, it's right there. Anyway, that's not good.

An Interface, should be exactly that, an interface. It shouldn't contain any data or code. I would expect C to implement getMyStruct() and to declare and manage _data and so on.

Having said that, the code you've posted isn't syntactically correct, so I'm not really clear on what error you're describing.
I'm away from my machine with the actual code so the above code was best endevour from memory to illustrate the concept.

You are right in that the Interface object should strickly speaking contain only abstract methods and no data. However, for debug purposes I move the data into the interface incase this strange issue I am having was connected to the downcast from specific class to the interface object. What I can say is that it isn't as the same behaviour is observed regardless of where the member attribute is placed.

Sorry if a bit confusing. I'll post some proper code and screen shots of the issue showing the change to the pointers later today. I took a chance and posted the above to get a 'head-start' in understanding valid reasons why C++ might be allowed to alter pointers!
Topic archived. No new replies allowed.