Puzzled as to why this works. Inheritance question

A

Angus

I have the following classes:

class call {
public:
long GetCallID();
void SetCallID(long callid);

private:
long m_CallID;
};

class tapicall : public call
{
public:
long GetTapiID();
void SetTapiID(long tapiid);

private:
long m_TapiID;
};


class iface
{
public:
call* FindCallByID(long callid);
void CreateNewCall(long callid);
void DeleteCall(long callid);

private:
std::list<call*> m_calllist;

};

Implementation here:
#include "call.h"

long call::GetCallID(){
return m_CallID;
}

void call::SetCallID(long callid){
m_CallID = callid;
}

long tapicall::GetTapiID(){
return m_TapiID;
}

void tapicall::SetTapiID(long tapiid){
m_TapiID = tapiid;
}

call* iface::FindCallByID(long callid){
std::list<call*>::const_iterator it;
for(it = m_calllist.begin(); it != m_calllist.end(); ++it){
if((*it)->GetCallID() == callid)
return *it;
}
return 0;
}

void iface::CreateNewCall(long callid){
call* pCall = new call;
pCall->SetCallID(callid);
m_calllist.push_back(pCall);
}

void iface::DeleteCall(long callid){
//do later
}


Then if I do this (in order as below):

void CInherittestDlg::OnOK()
{
m_iface.CreateNewCall(1);
}

void CInherittestDlg::OnBtnSet()
{
tapicall* ptcall = reinterpret_cast<tapicall*>(m_iface.FindCallByID
(1));
if(ptcall) {
ptcall->SetTapiID(3);
}
}

void CInherittestDlg::OnBtnGet()
{
long tapiid;
tapicall* ptcall = reinterpret_cast<tapicall*>(m_iface.FindCallByID
(1));
if(ptcall) {
tapiid=ptcall->GetTapiID();
}
}

Then I get the correct value back.

My understanding problem is that m_iface.FindCallByID returns a
call*. A call* stored in the std::list has only enough memory
reserved to be a call*

And we simply cast to a tapicall* and get the 'extra' bit which is the
TapiID. How does this work at a low level? Surely what is stored in
the iface list is only a call*?

Puzzled as to how it works.
 
A

alfps

I have the following classes:

class call {
public:
 long GetCallID();
 void SetCallID(long callid);

private:
  long m_CallID;

};

class tapicall : public call
{
public:
 long GetTapiID();
 void SetTapiID(long tapiid);

private:
  long m_TapiID;

};

+ code mostly equivalent to

tapicall* p = reinterpret_cast<tapicall*>( new call );
// Doing tapicall things here.

Then I get the correct value back.

You have undefined behavior.
My understanding problem is that m_iface.FindCallByID returns a
call*.  A call* stored in the std::list has only enough memory
reserved to be a call*

The pointed to object may or may not be large enough to accomodate
more data than a 'call'. But regardless you have undefined behavior,
accessing memory that's not guaranteed to belong to the pointed to
object.


Cheers & hth.,

- Alf
 
A

Angus

+ code mostly equivalent to



You have undefined behavior.




The pointed to object may or may not be large enough to accomodate
more data than a 'call'. But regardless you have undefined behavior,
accessing memory that's not guaranteed to belong to the pointed to
object.

Cheers & hth.,

- Alf- Hide quoted text -

- Show quoted text -

The place where I work uses this sort of technique a lot. Are you
saying this is not recommended?
 
A

alfps

The place where I work uses this sort of technique a lot.  Are you
saying this is not recommended?

Undefined Behavior is never recommended. Even when it apparently
"works" the slightest change, in source code or tool usage, can
produce a different effect, so it's a ticking bomb. However, a
sufficiently cynical, incompetent and dishonest manager or project
lead may hold the view that meeting a deadline is much more important
than delivering robust code, and that the buried problems may be
desirable because they'll likely yield at least one "fix it" contract.

If this is the case (weak management) then it's likely that your
workplace's code has at least a few functions of many hundred lines.

And if so then there's no hope of getting the technical right, and it
may then be dangerous to one's career to even mention it.


Cheers & hth. (even if slightly off-topic),

- Alf
 
J

James Kanze

On 24 Dec, 14:04, alfps <[email protected]> wrote:

[Concerning accessing unallocated memory...]
The place where I work uses this sort of technique a lot. Are
you saying this is not recommended?

He said it was undefined behavior. It's not a question of
"recommended"; undefined behavior means that it doesn't work, or
that it may not work all of the time. Frankly, if you're doing
this a lot, I'm surprised you haven't had core dumps.

I'd strongly recommend testing your code with Purify or
valgrind.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,690
Latest member
MacGyver

Latest Threads

Top