473,396 Members | 2,010 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Interface Programming the basics


// C3DRect supports IDraw and IShapeEdit.
class C3DRect : public IDraw, public IShapeEdit
{
public:
C3DRect();
virtual ~C3DRect();
// IDraw
virtual void Draw();
// IShapeEdit
virtual void Fill (FILLTYPE fType);
virtual void Inverse();
virtual void Stretch(int factor);
};

//-----------------------------------

// Here is the global 3D rect.
C3DRect* ptheRect;

// Functions to operate on the 3D rect.
void CreateThe3DRect();
void DestroyThe3DRect();

Implementing CreateThe3DRect() and DestroyThe3DRect() is trivial.
Simply use the new and delete keywords to create and destroy the
object:

// Creation function.
void CreateThe3DRect()
{
// Create a 3d-rect.
ptheRect = new C3DRect();
}
// Destroy the rectangle.
void DestroyThe3DRect()
{
// See ya!
delete ptheRect;
//--------------------
// This method returns interfaces to the client.
bool GetInterfaceFrom3DRect(INTERFACEID iid, void** iFacePtr)
{
if(ptheRect == NULL){
cout << "You forgot to create the 3DRect!" << endl;
return false;
}
if(iid == IDRAW){ // They want access to IDraw.
// Cast the client's pointer to the IDraw interface of
ptheRect.
*iFacePtr = (IDraw*) ptheRect;
return true;
}
if(iid == ISHAPEEDIT) { // They want access to IShapeEdit.
// Cast the client's pointer to the IShapeEdit interface of
ptheRect.
*iFacePtr = (IShapeEdit*) ptheRect;
return true;
}
// I have no clue what they want.
*iFacePtr = NULL; // Just to be safe.
cout << "C3DRect does not support interface ID: " << iid <<
endl<< endl;
return false;
}
//----------------------------------------------------
int main()
{
bool retVal = false;
IDraw* pDraw = NULL;
//IDraw3* pDraw3 = NULL;
IShapeEdit* pShapeEdit = NULL;

CreateThe3DRect();

// Can I get the IDraw interface from object?
retVal = GetInterfaceFrom3DRect(IDRAW, (void**)&pDraw);
if(retVal)
pDraw->Draw();
DestroyThe3DRect();

return 0;
}
//-----

help me understand this please.
are we simply casting pointers from one type to the next here?
when selecting the interface with GetInterfaceFrom3DRect ,i have
iFacePtr which is a void pointer and ptheRect.

*iFacePtr = (IDraw*) ptheRect; <-- i dont get this part.
here iFacePtr is of IDraw type.. now we have ptheRect which is of
C3DRect, taking that casting it to IDraw and assigning it to iFacePtr.

does this mean we are working with an instance of C3DRect but of type
IDraw?
how did we managed that?
doesn't this mean we can make an instance of an abstract class by type
casting it?
As you can see im confused any easy to digest explanation would be
great.

thank you

Aug 31 '07 #1
8 1974
On 2007-08-31 18:05, Lamefif wrote:
// C3DRect supports IDraw and IShapeEdit.
class C3DRect : public IDraw, public IShapeEdit
{
public:
C3DRect();
virtual ~C3DRect();
// IDraw
virtual void Draw();
// IShapeEdit
virtual void Fill (FILLTYPE fType);
virtual void Inverse();
virtual void Stretch(int factor);
};

//-----------------------------------

// Here is the global 3D rect.
C3DRect* ptheRect;

// Functions to operate on the 3D rect.
void CreateThe3DRect();
void DestroyThe3DRect();

Implementing CreateThe3DRect() and DestroyThe3DRect() is trivial.
Simply use the new and delete keywords to create and destroy the
object:

// Creation function.
void CreateThe3DRect()
{
// Create a 3d-rect.
ptheRect = new C3DRect();
}
// Destroy the rectangle.
void DestroyThe3DRect()
{
// See ya!
delete ptheRect;
//--------------------
// This method returns interfaces to the client.
bool GetInterfaceFrom3DRect(INTERFACEID iid, void** iFacePtr)
{
if(ptheRect == NULL){
cout << "You forgot to create the 3DRect!" << endl;
return false;
}
if(iid == IDRAW){ // They want access to IDraw.
// Cast the client's pointer to the IDraw interface of
ptheRect.
*iFacePtr = (IDraw*) ptheRect;
return true;
}
if(iid == ISHAPEEDIT) { // They want access to IShapeEdit.
// Cast the client's pointer to the IShapeEdit interface of
ptheRect.
*iFacePtr = (IShapeEdit*) ptheRect;
return true;
}
// I have no clue what they want.
*iFacePtr = NULL; // Just to be safe.
cout << "C3DRect does not support interface ID: " << iid <<
endl<< endl;
return false;
}
Really stupid function, could be implemented much easier and cleaner
with something like this:

IDraw* getIDraw() {
return dynamic_cast<IDraw*>(ptheRect);
}

IShapeEdit* getIShapeEdit() {
return dynamic_cast<IShapeEdit*>(ptheRect);
}

And let the user check if the returned pointer is NULL.
//----------------------------------------------------
int main()
{
bool retVal = false;
IDraw* pDraw = NULL;
//IDraw3* pDraw3 = NULL;
IShapeEdit* pShapeEdit = NULL;

CreateThe3DRect();

// Can I get the IDraw interface from object?
retVal = GetInterfaceFrom3DRect(IDRAW, (void**)&pDraw);
if(retVal)
pDraw->Draw();
DestroyThe3DRect();

return 0;
}
//-----

help me understand this please.
are we simply casting pointers from one type to the next here?
Yes.
when selecting the interface with GetInterfaceFrom3DRect ,i have
iFacePtr which is a void pointer and ptheRect.

*iFacePtr = (IDraw*) ptheRect; <-- i dont get this part.
Cast the pointer ptheRect to a pointer to an IDraw object. Except that
it is assigned to a pointer to void, so you end up with a void pointer.
here iFacePtr is of IDraw type.. now we have ptheRect which is of
C3DRect, taking that casting it to IDraw and assigning it to iFacePtr.

does this mean we are working with an instance of C3DRect but of type
IDraw?
Nope, just pointers.
how did we managed that?
doesn't this mean we can make an instance of an abstract class by type
casting it?
No, we can have pointers (ore references) to objects of an abstract
class, but you can never instantiate an abstract class. That's how
abstract classes can work as interfaces.

--
Erik Wikström
Aug 31 '07 #2
On Aug 31, 6:04 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-08-31 18:05, Lamefif wrote:
// C3DRect supports IDraw and IShapeEdit.
class C3DRect : public IDraw, public IShapeEdit
{
public:
C3DRect();
virtual ~C3DRect();
// IDraw
virtual void Draw();
// IShapeEdit
virtual void Fill (FILLTYPE fType);
virtual void Inverse();
virtual void Stretch(int factor);
};
//-----------------------------------
// Here is the global 3D rect.
C3DRect* ptheRect;
// Functions to operate on the 3D rect.
void CreateThe3DRect();
void DestroyThe3DRect();
Implementing CreateThe3DRect() and DestroyThe3DRect() is trivial.
Simply use the new and delete keywords to create and destroy the
object:
// Creation function.
void CreateThe3DRect()
{
// Create a 3d-rect.
ptheRect = new C3DRect();
}
// Destroy the rectangle.
void DestroyThe3DRect()
{
// See ya!
delete ptheRect;
//--------------------
// This method returns interfaces to the client.
bool GetInterfaceFrom3DRect(INTERFACEID iid, void** iFacePtr)
{
if(ptheRect == NULL){
cout << "You forgot to create the 3DRect!" << endl;
return false;
}
if(iid == IDRAW){ // They want access to IDraw.
// Cast the client's pointer to the IDraw interface of
ptheRect.
*iFacePtr = (IDraw*) ptheRect;
return true;
}
if(iid == ISHAPEEDIT) { // They want access to IShapeEdit.
// Cast the client's pointer to the IShapeEdit interface of
ptheRect.
*iFacePtr = (IShapeEdit*) ptheRect;
return true;
}
// I have no clue what they want.
*iFacePtr = NULL; // Just to be safe.
cout << "C3DRect does not support interface ID: " << iid <<
endl<< endl;
return false;
}

Really stupid function, could be implemented much easier and cleaner
with something like this:

IDraw* getIDraw() {
return dynamic_cast<IDraw*>(ptheRect);

}

IShapeEdit* getIShapeEdit() {
return dynamic_cast<IShapeEdit*>(ptheRect);

}

And let the user check if the returned pointer is NULL.
//----------------------------------------------------
int main()
{
bool retVal = false;
IDraw* pDraw = NULL;
//IDraw3* pDraw3 = NULL;
IShapeEdit* pShapeEdit = NULL;
CreateThe3DRect();
// Can I get the IDraw interface from object?
retVal = GetInterfaceFrom3DRect(IDRAW, (void**)&pDraw);
if(retVal)
pDraw->Draw();
DestroyThe3DRect();
return 0;
}
//-----
help me understand this please.
are we simply casting pointers from one type to the next here?

Yes.
when selecting the interface with GetInterfaceFrom3DRect ,i have
iFacePtr which is a void pointer and ptheRect.
*iFacePtr = (IDraw*) ptheRect; <-- i dont get this part.

Cast the pointer ptheRect to a pointer to an IDraw object. Except that
it is assigned to a pointer to void, so you end up with a void pointer.
here iFacePtr is of IDraw type.. now we have ptheRect which is of
C3DRect, taking that casting it to IDraw and assigning it to iFacePtr.
does this mean we are working with an instance of C3DRect but of type
IDraw?

Nope, just pointers.
how did we managed that?
doesn't this mean we can make an instance of an abstract class by type
casting it?

No, we can have pointers (ore references) to objects of an abstract
class, but you can never instantiate an abstract class. That's how
abstract classes can work as interfaces.

--
Erik Wikström
So where is pDraw pointing to, IDraw?
the draw() method of IDraw does not have a body, i mean we are getting
the functionality of the Draw method we have written in C3DRect().

and we are creating one instance of C3DRect with CreateThe3DRect().

a good book suggestion on the subject or article would be appreciated
thanks

Aug 31 '07 #3
On 2007-08-31 21:42, Lamefif wrote:
On Aug 31, 6:04 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
>On 2007-08-31 18:05, Lamefif wrote:
// C3DRect supports IDraw and IShapeEdit.
class C3DRect : public IDraw, public IShapeEdit
{
public:
C3DRect();
virtual ~C3DRect();
// IDraw
virtual void Draw();
// IShapeEdit
virtual void Fill (FILLTYPE fType);
virtual void Inverse();
virtual void Stretch(int factor);
};
//-----------------------------------
// Here is the global 3D rect.
C3DRect* ptheRect;
// Functions to operate on the 3D rect.
void CreateThe3DRect();
void DestroyThe3DRect();
Implementing CreateThe3DRect() and DestroyThe3DRect() is trivial.
Simply use the new and delete keywords to create and destroy the
object:
// Creation function.
void CreateThe3DRect()
{
// Create a 3d-rect.
ptheRect = new C3DRect();
}
// Destroy the rectangle.
void DestroyThe3DRect()
{
// See ya!
delete ptheRect;
//--------------------
// This method returns interfaces to the client.
bool GetInterfaceFrom3DRect(INTERFACEID iid, void** iFacePtr)
{
if(ptheRect == NULL){
cout << "You forgot to create the 3DRect!" << endl;
return false;
}
if(iid == IDRAW){ // They want access to IDraw.
// Cast the client's pointer to the IDraw interface of
ptheRect.
*iFacePtr = (IDraw*) ptheRect;
return true;
}
if(iid == ISHAPEEDIT) { // They want access to IShapeEdit.
// Cast the client's pointer to the IShapeEdit interface of
ptheRect.
*iFacePtr = (IShapeEdit*) ptheRect;
return true;
}
// I have no clue what they want.
*iFacePtr = NULL; // Just to be safe.
cout << "C3DRect does not support interface ID: " << iid <<
endl<< endl;
return false;
}

Really stupid function, could be implemented much easier and cleaner
with something like this:

IDraw* getIDraw() {
return dynamic_cast<IDraw*>(ptheRect);

}

IShapeEdit* getIShapeEdit() {
return dynamic_cast<IShapeEdit*>(ptheRect);

}

And let the user check if the returned pointer is NULL.
//----------------------------------------------------
int main()
{
bool retVal = false;
IDraw* pDraw = NULL;
//IDraw3* pDraw3 = NULL;
IShapeEdit* pShapeEdit = NULL;
CreateThe3DRect();
// Can I get the IDraw interface from object?
retVal = GetInterfaceFrom3DRect(IDRAW, (void**)&pDraw);
if(retVal)
pDraw->Draw();
DestroyThe3DRect();
return 0;
}
//-----
help me understand this please.
are we simply casting pointers from one type to the next here?

Yes.
when selecting the interface with GetInterfaceFrom3DRect ,i have
iFacePtr which is a void pointer and ptheRect.
*iFacePtr = (IDraw*) ptheRect; <-- i dont get this part.

Cast the pointer ptheRect to a pointer to an IDraw object. Except that
it is assigned to a pointer to void, so you end up with a void pointer.
here iFacePtr is of IDraw type.. now we have ptheRect which is of
C3DRect, taking that casting it to IDraw and assigning it to iFacePtr.
does this mean we are working with an instance of C3DRect but of type
IDraw?

Nope, just pointers.
how did we managed that?
doesn't this mean we can make an instance of an abstract class by type
casting it?

No, we can have pointers (ore references) to objects of an abstract
class, but you can never instantiate an abstract class. That's how
abstract classes can work as interfaces.

--
Erik Wikström

So where is pDraw pointing to, IDraw?
pDraw points to the C3DRect instance, same as ptheRect points to.
the draw() method of IDraw does not have a body, i mean we are getting
the functionality of the Draw method we have written in C3DRect().
Yes, since pDraw points to the C3DRect instance.
and we are creating one instance of C3DRect with CreateThe3DRect().

a good book suggestion on the subject or article would be appreciated
thanks
Any book describing polymorphic behaviour should do. The theory is the
same regardless which language you use. One way to look at it is that
the two pointers (ptheRect and pDraw) are two different interpretations
of the data they point to. ptheRect says that it points to a C3DRect
while pDraw claims to point to a IDraw. We both know that they both
point to a C3DRect, but since it behaves just like a IDraw we can also
treat it like one.

--
Erik Wikström
Aug 31 '07 #4
On Aug 31, 11:10 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-08-31 21:42, Lamefif wrote:
On Aug 31, 6:04 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-08-31 18:05, Lamefif wrote:
// C3DRect supports IDraw and IShapeEdit.
class C3DRect : public IDraw, public IShapeEdit
{
public:
C3DRect();
virtual ~C3DRect();
// IDraw
virtual void Draw();
// IShapeEdit
virtual void Fill (FILLTYPE fType);
virtual void Inverse();
virtual void Stretch(int factor);
};
//-----------------------------------
// Here is the global 3D rect.
C3DRect* ptheRect;
// Functions to operate on the 3D rect.
void CreateThe3DRect();
void DestroyThe3DRect();
Implementing CreateThe3DRect() and DestroyThe3DRect() is trivial.
Simply use the new and delete keywords to create and destroy the
object:
// Creation function.
void CreateThe3DRect()
{
// Create a 3d-rect.
ptheRect = new C3DRect();
}
// Destroy the rectangle.
void DestroyThe3DRect()
{
// See ya!
delete ptheRect;
//--------------------
// This method returns interfaces to the client.
bool GetInterfaceFrom3DRect(INTERFACEID iid, void** iFacePtr)
{
if(ptheRect == NULL){
cout << "You forgot to create the 3DRect!" << endl;
return false;
}
if(iid == IDRAW){ // They want access to IDraw.
// Cast the client's pointer to the IDraw interface of
ptheRect.
*iFacePtr = (IDraw*) ptheRect;
return true;
}
if(iid == ISHAPEEDIT) { // They want access to IShapeEdit.
// Cast the client's pointer to the IShapeEdit interface of
ptheRect.
*iFacePtr = (IShapeEdit*) ptheRect;
return true;
}
// I have no clue what they want.
*iFacePtr = NULL; // Just to be safe.
cout << "C3DRect does not support interface ID: " << iid <<
endl<< endl;
return false;
}
Really stupid function, could be implemented much easier and cleaner
with something like this:
IDraw* getIDraw() {
return dynamic_cast<IDraw*>(ptheRect);
}
IShapeEdit* getIShapeEdit() {
return dynamic_cast<IShapeEdit*>(ptheRect);
}
And let the user check if the returned pointer is NULL.
//----------------------------------------------------
int main()
{
bool retVal = false;
IDraw* pDraw = NULL;
//IDraw3* pDraw3 = NULL;
IShapeEdit* pShapeEdit = NULL;
CreateThe3DRect();
// Can I get the IDraw interface from object?
retVal = GetInterfaceFrom3DRect(IDRAW, (void**)&pDraw);
if(retVal)
pDraw->Draw();
DestroyThe3DRect();
return 0;
}
//-----
help me understand this please.
are we simply casting pointers from one type to the next here?
Yes.
when selecting the interface with GetInterfaceFrom3DRect ,i have
iFacePtr which is a void pointer and ptheRect.
*iFacePtr = (IDraw*) ptheRect; <-- i dont get this part.
Cast the pointer ptheRect to a pointer to an IDraw object. Except that
it is assigned to a pointer to void, so you end up with a void pointer.
here iFacePtr is of IDraw type.. now we have ptheRect which is of
C3DRect, taking that casting it to IDraw and assigning it to iFacePtr.
does this mean we are working with an instance of C3DRect but of type
IDraw?
Nope, just pointers.
how did we managed that?
doesn't this mean we can make an instance of an abstract class by type
casting it?
No, we can have pointers (ore references) to objects of an abstract
class, but you can never instantiate an abstract class. That's how
abstract classes can work as interfaces.
--
Erik Wikström
So where is pDraw pointing to, IDraw?

pDraw points to the C3DRect instance, same as ptheRect points to.
the draw() method of IDraw does not have a body, i mean we are getting
the functionality of the Draw method we have written in C3DRect().

Yes, since pDraw points to the C3DRect instance.
and we are creating one instance of C3DRect with CreateThe3DRect().
a good book suggestion on the subject or article would be appreciated
thanks

Any book describing polymorphic behaviour should do. The theory is the
same regardless which language you use. One way to look at it is that
the two pointers (ptheRect and pDraw) are two different interpretations
of the data they point to. ptheRect says that it points to a C3DRect
while pDraw claims to point to a IDraw. We both know that they both
point to a C3DRect, but since it behaves just like a IDraw we can also
treat it like one.

--
Erik Wikström
ok i think i need just a little more pushing in the right direction.

pDraw and ptheRect both point to the same instance.
But treat it differently because they are declared to be of different
type to begin with?

i mean if pDraw points to C3DRect why aren't we seeing the rest of the
methods but only draw(), why are they hidden?

thanks for your replies, i appreciated :)

Sep 1 '07 #5
On 2007-09-01 03:49, Lamefif wrote:
On Aug 31, 11:10 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
>On 2007-08-31 21:42, Lamefif wrote:
On Aug 31, 6:04 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-08-31 18:05, Lamefif wrote:
// C3DRect supports IDraw and IShapeEdit.
class C3DRect : public IDraw, public IShapeEdit
{
public:
C3DRect();
virtual ~C3DRect();
// IDraw
virtual void Draw();
// IShapeEdit
virtual void Fill (FILLTYPE fType);
virtual void Inverse();
virtual void Stretch(int factor);
};
//-----------------------------------
// Here is the global 3D rect.
C3DRect* ptheRect;
// Functions to operate on the 3D rect.
void CreateThe3DRect();
void DestroyThe3DRect();
Implementing CreateThe3DRect() and DestroyThe3DRect() is trivial.
Simply use the new and delete keywords to create and destroy the
object:
// Creation function.
void CreateThe3DRect()
{
// Create a 3d-rect.
ptheRect = new C3DRect();
}
// Destroy the rectangle.
void DestroyThe3DRect()
{
// See ya!
delete ptheRect;
//--------------------
// This method returns interfaces to the client.
bool GetInterfaceFrom3DRect(INTERFACEID iid, void** iFacePtr)
{
if(ptheRect == NULL){
cout << "You forgot to create the 3DRect!" << endl;
return false;
}
if(iid == IDRAW){ // They want access to IDraw.
// Cast the client's pointer to the IDraw interface of
ptheRect.
*iFacePtr = (IDraw*) ptheRect;
return true;
}
if(iid == ISHAPEEDIT) { // They want access to IShapeEdit.
// Cast the client's pointer to the IShapeEdit interface of
ptheRect.
*iFacePtr = (IShapeEdit*) ptheRect;
return true;
}
// I have no clue what they want.
*iFacePtr = NULL; // Just to be safe.
cout << "C3DRect does not support interface ID: " << iid <<
endl<< endl;
return false;
}
>Really stupid function, could be implemented much easier and cleaner
with something like this:
>IDraw* getIDraw() {
return dynamic_cast<IDraw*>(ptheRect);
>}
>IShapeEdit* getIShapeEdit() {
return dynamic_cast<IShapeEdit*>(ptheRect);
>}
>And let the user check if the returned pointer is NULL.
//----------------------------------------------------
int main()
{
bool retVal = false;
IDraw* pDraw = NULL;
//IDraw3* pDraw3 = NULL;
IShapeEdit* pShapeEdit = NULL;
CreateThe3DRect();
// Can I get the IDraw interface from object?
retVal = GetInterfaceFrom3DRect(IDRAW, (void**)&pDraw);
if(retVal)
pDraw->Draw();
DestroyThe3DRect();
return 0;
}
//-----
help me understand this please.
are we simply casting pointers from one type to the next here?
>Yes.
when selecting the interface with GetInterfaceFrom3DRect ,i have
iFacePtr which is a void pointer and ptheRect.
*iFacePtr = (IDraw*) ptheRect; <-- i dont get this part.
>Cast the pointer ptheRect to a pointer to an IDraw object. Except that
it is assigned to a pointer to void, so you end up with a void pointer.
here iFacePtr is of IDraw type.. now we have ptheRect which is of
C3DRect, taking that casting it to IDraw and assigning it to iFacePtr.
does this mean we are working with an instance of C3DRect but of type
IDraw?
>Nope, just pointers.
how did we managed that?
doesn't this mean we can make an instance of an abstract class by type
casting it?
>No, we can have pointers (ore references) to objects of an abstract
class, but you can never instantiate an abstract class. That's how
abstract classes can work as interfaces.
>--
Erik Wikström
So where is pDraw pointing to, IDraw?

pDraw points to the C3DRect instance, same as ptheRect points to.
the draw() method of IDraw does not have a body, i mean we are getting
the functionality of the Draw method we have written in C3DRect().

Yes, since pDraw points to the C3DRect instance.
and we are creating one instance of C3DRect with CreateThe3DRect().
a good book suggestion on the subject or article would be appreciated
thanks

Any book describing polymorphic behaviour should do. The theory is the
same regardless which language you use. One way to look at it is that
the two pointers (ptheRect and pDraw) are two different interpretations
of the data they point to. ptheRect says that it points to a C3DRect
while pDraw claims to point to a IDraw. We both know that they both
point to a C3DRect, but since it behaves just like a IDraw we can also
treat it like one.

--
Erik Wikström

ok i think i need just a little more pushing in the right direction.

pDraw and ptheRect both point to the same instance.
But treat it differently because they are declared to be of different
type to begin with?
Yes.
i mean if pDraw points to C3DRect why aren't we seeing the rest of the
methods but only draw(), why are they hidden?
Because compilers are stupid and trust the programmer. This means that
when we access the data pointed to by ptheRect it will interpret the
data as a C3DRect, and when accessing it through pDraw it will interpret
it as an IDraw.

This is important when IDraw is not an abstract class, since if you then
make a copy of what pDraw points to, only the IDraw portion will be
copied and the rest ignored. This is called slicing and is usually not
what you want.

--
Erik Wikström
Sep 1 '07 #6
On Sep 1, 10:15 am, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-09-01 03:49, Lamefif wrote:
On Aug 31, 11:10 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-08-31 21:42, Lamefif wrote:
On Aug 31, 6:04 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-08-31 18:05, Lamefif wrote:
// C3DRect supports IDraw and IShapeEdit.
class C3DRect : public IDraw, public IShapeEdit
{
public:
C3DRect();
virtual ~C3DRect();
// IDraw
virtual void Draw();
// IShapeEdit
virtual void Fill (FILLTYPE fType);
virtual void Inverse();
virtual void Stretch(int factor);
};
//-----------------------------------
// Here is the global 3D rect.
C3DRect* ptheRect;
// Functions to operate on the 3D rect.
void CreateThe3DRect();
void DestroyThe3DRect();
Implementing CreateThe3DRect() and DestroyThe3DRect() is trivial.
Simply use the new and delete keywords to create and destroy the
object:
// Creation function.
void CreateThe3DRect()
{
// Create a 3d-rect.
ptheRect = new C3DRect();
}
// Destroy the rectangle.
void DestroyThe3DRect()
{
// See ya!
delete ptheRect;
//--------------------
// This method returns interfaces to the client.
bool GetInterfaceFrom3DRect(INTERFACEID iid, void** iFacePtr)
{
if(ptheRect == NULL){
cout << "You forgot to create the 3DRect!" << endl;
return false;
}
if(iid == IDRAW){ // They want access to IDraw.
// Cast the client's pointer to the IDraw interface of
ptheRect.
*iFacePtr = (IDraw*) ptheRect;
return true;
}
if(iid == ISHAPEEDIT) { // They want access to IShapeEdit.
// Cast the client's pointer to the IShapeEdit interface of
ptheRect.
*iFacePtr = (IShapeEdit*) ptheRect;
return true;
}
// I have no clue what they want.
*iFacePtr = NULL; // Just to be safe.
cout << "C3DRect does not support interface ID: " << iid <<
endl<< endl;
return false;
}
Really stupid function, could be implemented much easier and cleaner
with something like this:
IDraw* getIDraw() {
return dynamic_cast<IDraw*>(ptheRect);
}
IShapeEdit* getIShapeEdit() {
return dynamic_cast<IShapeEdit*>(ptheRect);
}
And let the user check if the returned pointer is NULL.
//----------------------------------------------------
int main()
{
bool retVal = false;
IDraw* pDraw = NULL;
//IDraw3* pDraw3 = NULL;
IShapeEdit* pShapeEdit = NULL;
CreateThe3DRect();
// Can I get the IDraw interface from object?
retVal = GetInterfaceFrom3DRect(IDRAW, (void**)&pDraw);
if(retVal)
pDraw->Draw();
DestroyThe3DRect();
return 0;
}
//-----
help me understand this please.
are we simply casting pointers from one type to the next here?
Yes.
when selecting the interface with GetInterfaceFrom3DRect ,i have
iFacePtr which is a void pointer and ptheRect.
*iFacePtr = (IDraw*) ptheRect; <-- i dont get this part.
Cast the pointer ptheRect to a pointer to an IDraw object. Except that
it is assigned to a pointer to void, so you end up with a void pointer.
here iFacePtr is of IDraw type.. now we have ptheRect which is of
C3DRect, taking that casting it to IDraw and assigning it to iFacePtr.
does this mean we are working with an instance of C3DRect but of type
IDraw?
Nope, just pointers.
how did we managed that?
doesn't this mean we can make an instance of an abstract class bytype
casting it?
No, we can have pointers (ore references) to objects of an abstract
class, but you can never instantiate an abstract class. That's how
abstract classes can work as interfaces.
--
Erik Wikström
So where is pDraw pointing to, IDraw?
pDraw points to the C3DRect instance, same as ptheRect points to.
the draw() method of IDraw does not have a body, i mean we are getting
the functionality of the Draw method we have written in C3DRect().
Yes, since pDraw points to the C3DRect instance.
and we are creating one instance of C3DRect with CreateThe3DRect().
a good book suggestion on the subject or article would be appreciated
thanks
Any book describing polymorphic behaviour should do. The theory is the
same regardless which language you use. One way to look at it is that
the two pointers (ptheRect and pDraw) are two different interpretations
of the data they point to. ptheRect says that it points to a C3DRect
while pDraw claims to point to a IDraw. We both know that they both
point to a C3DRect, but since it behaves just like a IDraw we can also
treat it like one.
--
Erik Wikström
ok i think i need just a little more pushing in the right direction.
pDraw and ptheRect both point to the same instance.
But treat it differently because they are declared to be of different
type to begin with?

Yes.
i mean if pDraw points to C3DRect why aren't we seeing the rest of the
methods but only draw(), why are they hidden?

Because compilers are stupid and trust the programmer. This means that
when we access the data pointed to by ptheRect it will interpret the
data as a C3DRect, and when accessing it through pDraw it will interpret
it as an IDraw.

This is important when IDraw is not an abstract class, since if you then
make a copy of what pDraw points to, only the IDraw portion will be
copied and the rest ignored. This is called slicing and is usually not
what you want.

--
Erik Wikström
thanks to you im a lot less confused :)

you said earlier that GetInterfaceFrom3DRect is stupid, and should be
replaces with something like:
IDraw* getIDraw() {
return dynamic_cast<IDraw*>(ptheRect);

}
getIDraw being a method of C3DRect?

this seems to eliminate the need for interface ID's, if is not too
much to ask what other changes would you make.
i like to see how would you go about designing this, it dont matter if
the code is complex or rather i prefer it :)

and how would you go about implementing this in the main method,
something like?

IDraw* pDraw = NULL;

CreateThe3DRect();

pDraw = ptheRect->getIDraw();
..
..

DestroyThe3DRect();
Thanks again

Sep 1 '07 #7
On 2007-09-01 14:11, Lamefif wrote:
On Sep 1, 10:15 am, Erik Wikström <Erik-wikst...@telia.comwrote:
>On 2007-09-01 03:49, Lamefif wrote:
On Aug 31, 11:10 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-08-31 21:42, Lamefif wrote:
On Aug 31, 6:04 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-08-31 18:05, Lamefif wrote:
// C3DRect supports IDraw and IShapeEdit.
class C3DRect : public IDraw, public IShapeEdit
{
public:
C3DRect();
virtual ~C3DRect();
// IDraw
virtual void Draw();
// IShapeEdit
virtual void Fill (FILLTYPE fType);
virtual void Inverse();
virtual void Stretch(int factor);
};
//-----------------------------------
// Here is the global 3D rect.
C3DRect* ptheRect;
// Functions to operate on the 3D rect.
void CreateThe3DRect();
void DestroyThe3DRect();
Implementing CreateThe3DRect() and DestroyThe3DRect() is trivial.
Simply use the new and delete keywords to create and destroy the
object:
// Creation function.
void CreateThe3DRect()
{
// Create a 3d-rect.
ptheRect = new C3DRect();
}
// Destroy the rectangle.
void DestroyThe3DRect()
{
// See ya!
delete ptheRect;
//--------------------
// This method returns interfaces to the client.
bool GetInterfaceFrom3DRect(INTERFACEID iid, void** iFacePtr)
{
if(ptheRect == NULL){
cout << "You forgot to create the 3DRect!" << endl;
return false;
}
if(iid == IDRAW){ // They want access to IDraw.
// Cast the client's pointer to the IDraw interface of
ptheRect.
*iFacePtr = (IDraw*) ptheRect;
return true;
}
if(iid == ISHAPEEDIT) { // They want access to IShapeEdit.
// Cast the client's pointer to the IShapeEdit interface of
ptheRect.
*iFacePtr = (IShapeEdit*) ptheRect;
return true;
}
// I have no clue what they want.
*iFacePtr = NULL; // Just to be safe.
cout << "C3DRect does not support interface ID: " << iid <<
endl<< endl;
return false;
}
>Really stupid function, could be implemented much easier and cleaner
with something like this:
>IDraw* getIDraw() {
return dynamic_cast<IDraw*>(ptheRect);
>}
>IShapeEdit* getIShapeEdit() {
return dynamic_cast<IShapeEdit*>(ptheRect);
>}
>And let the user check if the returned pointer is NULL.
//----------------------------------------------------
int main()
{
bool retVal = false;
IDraw* pDraw = NULL;
//IDraw3* pDraw3 = NULL;
IShapeEdit* pShapeEdit = NULL;
CreateThe3DRect();
// Can I get the IDraw interface from object?
retVal = GetInterfaceFrom3DRect(IDRAW, (void**)&pDraw);
if(retVal)
pDraw->Draw();
DestroyThe3DRect();
return 0;
}
//-----
help me understand this please.
are we simply casting pointers from one type to the next here?
>Yes.
when selecting the interface with GetInterfaceFrom3DRect ,i have
iFacePtr which is a void pointer and ptheRect.
*iFacePtr = (IDraw*) ptheRect; <-- i dont get this part.
>Cast the pointer ptheRect to a pointer to an IDraw object. Except that
it is assigned to a pointer to void, so you end up with a void pointer.
here iFacePtr is of IDraw type.. now we have ptheRect which is of
C3DRect, taking that casting it to IDraw and assigning it to iFacePtr.
does this mean we are working with an instance of C3DRect but of type
IDraw?
>Nope, just pointers.
how did we managed that?
doesn't this mean we can make an instance of an abstract class by type
casting it?
>No, we can have pointers (ore references) to objects of an abstract
class, but you can never instantiate an abstract class. That's how
abstract classes can work as interfaces.
>--
Erik Wikström
So where is pDraw pointing to, IDraw?
>pDraw points to the C3DRect instance, same as ptheRect points to.
the draw() method of IDraw does not have a body, i mean we are getting
the functionality of the Draw method we have written in C3DRect().
>Yes, since pDraw points to the C3DRect instance.
and we are creating one instance of C3DRect with CreateThe3DRect().
a good book suggestion on the subject or article would be appreciated
thanks
>Any book describing polymorphic behaviour should do. The theory is the
same regardless which language you use. One way to look at it is that
the two pointers (ptheRect and pDraw) are two different interpretations
of the data they point to. ptheRect says that it points to a C3DRect
while pDraw claims to point to a IDraw. We both know that they both
point to a C3DRect, but since it behaves just like a IDraw we can also
treat it like one.
>--
Erik Wikström
ok i think i need just a little more pushing in the right direction.
pDraw and ptheRect both point to the same instance.
But treat it differently because they are declared to be of different
type to begin with?

Yes.
i mean if pDraw points to C3DRect why aren't we seeing the rest of the
methods but only draw(), why are they hidden?

Because compilers are stupid and trust the programmer. This means that
when we access the data pointed to by ptheRect it will interpret the
data as a C3DRect, and when accessing it through pDraw it will interpret
it as an IDraw.

This is important when IDraw is not an abstract class, since if you then
make a copy of what pDraw points to, only the IDraw portion will be
copied and the rest ignored. This is called slicing and is usually not
what you want.

--
Erik Wikström

thanks to you im a lot less confused :)

you said earlier that GetInterfaceFrom3DRect is stupid, and should be
replaces with something like:
IDraw* getIDraw() {
return dynamic_cast<IDraw*>(ptheRect);

}
getIDraw being a method of C3DRect?

this seems to eliminate the need for interface ID's, if is not too
much to ask what other changes would you make.
i like to see how would you go about designing this, it dont matter if
the code is complex or rather i prefer it :)

and how would you go about implementing this in the main method,
something like?
I'd get rid of the global variable, CreateThe3DRect, DestroyThe3DRect,
and GetInterfaceFrom3DRect. They don't serve any purpose that I can see.
IDraw* pDraw = NULL;

CreateThe3DRect();

pDraw = ptheRect->getIDraw();
We don't need a IDraw pointer to call Draw, we can do that from a
C3DRect pointer as well. In fact we don't need any pointers at all since
none of the code makes use of any polymorphic behaviour.
Since I don't know what the code is supposed to do I'd reduce it to the
minimum which should reproduce the same results:

//-----------------------------------

enum FillType { Solid, Dots, Stripes };

class IDraw
{
public:
virtual void Draw() = 0;
};

class IShapeEdit
{
public:
virtual void Fill (FillType fType) = 0;
virtual void Inverse() = 0;
virtual void Stretch(int factor) = 0;
};

//-----------------------------------

class C3DRect : public IDraw, public IShapeEdit
{
public:
C3DRect();
virtual ~C3DRect();
// IDraw
virtual void Draw();
// IShapeEdit
virtual void Fill (FillType fType);
virtual void Inverse();
virtual void Stretch(int factor);
};

//-----------------------------------

int main()
{
C3DRect rect;
rect.Draw();
return 0;
}

Notice the "= 0" at end of the function declarations in the interfaces,
this means that the functions are pure virtual and requires the user to
provide an overload in all classes inheriting from it. I use it to
indicate that those classes are pure interfaces with no implementation.

--
Erik Wikström
Sep 1 '07 #8
On Sep 1, 2:14 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-09-01 14:11, Lamefif wrote:
On Sep 1, 10:15 am, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-09-01 03:49, Lamefif wrote:
On Aug 31, 11:10 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-08-31 21:42, Lamefif wrote:
On Aug 31, 6:04 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-08-31 18:05, Lamefif wrote:
// C3DRect supports IDraw and IShapeEdit.
class C3DRect : public IDraw, public IShapeEdit
{
public:
C3DRect();
virtual ~C3DRect();
// IDraw
virtual void Draw();
// IShapeEdit
virtual void Fill (FILLTYPE fType);
virtual void Inverse();
virtual void Stretch(int factor);
};
//-----------------------------------
// Here is the global 3D rect.
C3DRect* ptheRect;
// Functions to operate on the 3D rect.
void CreateThe3DRect();
void DestroyThe3DRect();
Implementing CreateThe3DRect() and DestroyThe3DRect() is trivial.
Simply use the new and delete keywords to create and destroy the
object:
// Creation function.
void CreateThe3DRect()
{
// Create a 3d-rect.
ptheRect = new C3DRect();
}
// Destroy the rectangle.
void DestroyThe3DRect()
{
// See ya!
delete ptheRect;
//--------------------
// This method returns interfaces to the client.
bool GetInterfaceFrom3DRect(INTERFACEID iid, void** iFacePtr)
{
if(ptheRect == NULL){
cout << "You forgot to create the 3DRect!" << endl;
return false;
}
if(iid == IDRAW){ // They want access to IDraw.
// Cast the client's pointer to the IDraw interface of
ptheRect.
*iFacePtr = (IDraw*) ptheRect;
return true;
}
if(iid == ISHAPEEDIT) { // They want access to IShapeEdit.
// Cast the client's pointer to the IShapeEdit interface of
ptheRect.
*iFacePtr = (IShapeEdit*) ptheRect;
return true;
}
// I have no clue what they want.
*iFacePtr = NULL; // Just to be safe.
cout << "C3DRect does not support interface ID: " << iid <<
endl<< endl;
return false;
}
Really stupid function, could be implemented much easier and cleaner
with something like this:
IDraw* getIDraw() {
return dynamic_cast<IDraw*>(ptheRect);
}
IShapeEdit* getIShapeEdit() {
return dynamic_cast<IShapeEdit*>(ptheRect);
}
And let the user check if the returned pointer is NULL.
//----------------------------------------------------
int main()
{
bool retVal = false;
IDraw* pDraw = NULL;
//IDraw3* pDraw3 = NULL;
IShapeEdit* pShapeEdit = NULL;
CreateThe3DRect();
// Can I get the IDraw interface from object?
retVal = GetInterfaceFrom3DRect(IDRAW, (void**)&pDraw);
if(retVal)
pDraw->Draw();
DestroyThe3DRect();
return 0;
}
//-----
help me understand this please.
are we simply casting pointers from one type to the next here?
Yes.
when selecting the interface with GetInterfaceFrom3DRect ,i have
iFacePtr which is a void pointer and ptheRect.
*iFacePtr = (IDraw*) ptheRect; <-- i dont get this part.
Cast the pointer ptheRect to a pointer to an IDraw object. Except that
it is assigned to a pointer to void, so you end up with a void pointer.
here iFacePtr is of IDraw type.. now we have ptheRect which isof
C3DRect, taking that casting it to IDraw and assigning it to iFacePtr.
does this mean we are working with an instance of C3DRect but of type
IDraw?
Nope, just pointers.
how did we managed that?
doesn't this mean we can make an instance of an abstract classby type
casting it?
No, we can have pointers (ore references) to objects of an abstract
class, but you can never instantiate an abstract class. That's how
abstract classes can work as interfaces.
--
Erik Wikström
So where is pDraw pointing to, IDraw?
pDraw points to the C3DRect instance, same as ptheRect points to.
the draw() method of IDraw does not have a body, i mean we are getting
the functionality of the Draw method we have written in C3DRect().
Yes, since pDraw points to the C3DRect instance.
and we are creating one instance of C3DRect with CreateThe3DRect().
a good book suggestion on the subject or article would be appreciated
thanks
Any book describing polymorphic behaviour should do. The theory is the
same regardless which language you use. One way to look at it is that
the two pointers (ptheRect and pDraw) are two different interpretations
of the data they point to. ptheRect says that it points to a C3DRect
while pDraw claims to point to a IDraw. We both know that they both
point to a C3DRect, but since it behaves just like a IDraw we can also
treat it like one.
--
Erik Wikström
ok i think i need just a little more pushing in the right direction.
pDraw and ptheRect both point to the same instance.
But treat it differently because they are declared to be of different
type to begin with?
Yes.
i mean if pDraw points to C3DRect why aren't we seeing the rest of the
methods but only draw(), why are they hidden?
Because compilers are stupid and trust the programmer. This means that
when we access the data pointed to by ptheRect it will interpret the
data as a C3DRect, and when accessing it through pDraw it will interpret
it as an IDraw.
This is important when IDraw is not an abstract class, since if you then
make a copy of what pDraw points to, only the IDraw portion will be
copied and the rest ignored. This is called slicing and is usually not
what you want.
--
Erik Wikström
thanks to you im a lot less confused :)
you said earlier that GetInterfaceFrom3DRect is stupid, and should be
replaces with something like:
IDraw* getIDraw() {
return dynamic_cast<IDraw*>(ptheRect);
}
getIDraw being a method of C3DRect?
this seems to eliminate the need for interface ID's, if is not too
much to ask what other changes would you make.
i like to see how would you go about designing this, it dont matter if
the code is complex or rather i prefer it :)
and how would you go about implementing this in the main method,
something like?

I'd get rid of the global variable, CreateThe3DRect, DestroyThe3DRect,
and GetInterfaceFrom3DRect. They don't serve any purpose that I can see.
IDraw* pDraw = NULL;
CreateThe3DRect();
pDraw = ptheRect->getIDraw();

We don't need a IDraw pointer to call Draw, we can do that from a
C3DRect pointer as well. In fact we don't need any pointers at all since
none of the code makes use of any polymorphic behaviour.

Since I don't know what the code is supposed to do I'd reduce it to the
minimum which should reproduce the same results:

//-----------------------------------

enum FillType { Solid, Dots, Stripes };

class IDraw
{
public:
virtual void Draw() = 0;

};

class IShapeEdit
{
public:
virtual void Fill (FillType fType) = 0;
virtual void Inverse() = 0;
virtual void Stretch(int factor) = 0;

};

//-----------------------------------

class C3DRect : public IDraw, public IShapeEdit
{
public:
C3DRect();
virtual ~C3DRect();
// IDraw
virtual void Draw();
// IShapeEdit
virtual void Fill (FillType fType);
virtual void Inverse();
virtual void Stretch(int factor);

};

//-----------------------------------

int main()
{
C3DRect rect;
rect.Draw();
return 0;

}

Notice the "= 0" at end of the function declarations in the interfaces,
this means that the functions are pure virtual and requires the user to
provide an overload in all classes inheriting from it. I use it to
indicate that those classes are pure interfaces with no implementation.

--
Erik Wikström
Thank you, been of great help. The book im reading "Developer's
Workshop to COM and ATL 3.0", its aim is towards COM programming. This
part was brush up on Interfaces.

Maybe this unnecessary complexity is needed later.

Sep 1 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Mark | last post by:
Hello. I am new to programming and Python and was wondering if someone could help get me started. I picked Python to start learning to prgram because of some things I have read about it (easy to...
1
by: manish | last post by:
Hi, I am a fresher in the programming field i.e although I have done programming at the basic level but at professional level I am very new and I am facing many problems. These probllems are...
6
by: John Walton | last post by:
Hello, everyone. I just began school, and they already assigned us science fair. Since I'm in 8th grade, I get to do demonstrations for our projects. I'm probably going to demonstrate Python's...
3
by: user | last post by:
Hi all, At the outset, I regret having to post this slightly OT post here. However, I strongly feel that people in this group would be the best to advise me on my predicament. I am working as...
42
by: Kevin Spencer | last post by:
Is it just me, or am I really observing a trend away from analysis and probem-solving amongst programmers? Let me be more specific: It seems that every day, in greater numbers, people are coming...
17
by: CoreyWhite | last post by:
I bought this book years ago, when I was just learning C++. Since then I've gone through every math course offered at my college, taken courses on coding C & thinking in terms how how to make the...
22
by: amygdala | last post by:
Hi, I'm trying to grasp OOP to build an interface using class objects that lets me access database tables easily. You have probably seen this before, or maybe even built it yourself at some...
8
by: rn5a | last post by:
Suppose I have the following class code: Imports System Imports System.Data Imports System.Data.SqlClient Public Class DBSettings Private sqlCmd As SqlCommand Private sqlConn As...
7
Banfa
by: Banfa | last post by:
Posted by Ganon11 So, you want to learn how to program! Good for you! Programming is a very intruiging and fun activity to pick up, and it's also a great career choice if you like it! Finally,...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.