Link to home
Start Free TrialLog in
Avatar of Hypo
HypoFlag for Sweden

asked on

Pointers and classes

In Delphi, you "reach" a class and its functions by a pointer...

TLabel(PointerToALabel).Caption := '1';

So... In a VC++ project I'm working on I've got a list of pointers to several different classes, I wonder what I should write to get the same result I can get in delphi.

e.g. what in VC++ is equal to Delhi's, TObject(Pointer).Something;
Avatar of yonat
yonat

PointerToALabel->Caption = "1";
If you mean what I think you mean, you need to use the -> operator.  This is the pointer equivalent to the . operator.

For example, if you had a class CMyClass and had one object of that class and a pointer to an object of that class you would use

Object.Function for the object
Pointer->Function for the pointer.
Avatar of Hypo

ASKER

I'm sorry but that's not the problem...
I've already used pointers like that before... The problem is that I have pointers that points to different kinds of classes.  

(
p[1] could point to a CMyClass and p[2] could point to a CYourClass
)

I know (by a control variable) wich kind of class each pointer points to, but how can I get access to this class, using the pointer?
  If your classes have something in common you can
define a superclass, derive both classes from it and define
an array of objects of the superclass.

  Ex:

class SuperClass
{
  //blah blah blah
};

class CMyClass : public SuperClass
{
};

class CYourClass : public SuperClass
{
};

....

SuperClass *vet[10];

....

CMyClass *myclass = vet[1];
CYourClass *yourclass = vet[2];

 now, you can access your members:

   myclass->mymember();

   yourclass->yourmember();

The other option is to use casting to convert from one type to another.  In this case to convert a pointer from pointing from one type to another.  In general this is not a safe thing to do and should be avoid whenever possible. If you are careful, it can be done safely though.

for example

class ACls
{
   int I;
};

class BCls
{
   double D;
}

ACls A;
BCls B;
void *Array[2];

Array[0] = &A; //make first entry point to an ACls object.
Array[1] = &B; //make second entry point to an BCls object.

int i1 = Array[0]->I; // Error.
int i2 = ((ACls *)Array[0])->I; // Okay.  This conversion
           // compiles AND works because the 1st entry does point
           // an ACls object.
int i3 = ((ACls *)Array[1])->I; // ERROR.  This compiles, but fails
           // to work right because the 2nd entry does not point
            // to an ACls object.


ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
There is a much  safer alternative.

First, build a polymorphic base class:

    class Base
    {
    public:
        virtual ~Base() = 0;
    };

    Base::~Base() {}

Next, derive your classes from it:

    class CMyClass: public Base
    {
    public:
        int I;
    };

    class CYourClass: public Base
    {
    public:
        int J;
    };

Assume you have an array of pointers:

    const int size = 2;
    Base* p[size];
    p[0] = new CMyClass;
    p[1] = new CYourClass;

And now comes the fun part:

    for (int i = 0; i < size; ++i)
    {
        CMyClass* p1;
        if (p1 = dynamic_cast<CMyClass*>(p[i]))
            p1->I = 1;

        CYourClass* p2;
        if (p2 = dynamic_cast<CYourClass*>(p[i]))
            p2->J = 2;
    }

Can't go wrong...
you could try something like this:

void SomeFunction(void)
{
  CObject* pMyObject = new CMyClass;
  if(pMyObject->IsKindOf(RUNTIME_CLASS  
    (CMyClass)))
{
   //if IsKindOf is true, then cast is all right
   CMyClass* pmyClass = (CMyClass*) pMyObject;
   // more code...

delete pmyClass;
delete [MyObject];
} // end SomeFunction()
Avatar of Zoppo
captainkirk, that's MFC and not C++ ...

ZOPPO
>> There is a much  safer alternative.
>>
>> First, build a polymorphic base class:
Binder, had already suggested that.  I was suggesting an alternative because, I don't beleive that is the sort of case he has.  I.e. I beleive the classes already exist and may not inheirit from a base class.

>> MFC and not C++ ...
Actually wouldn't it be "MFC AND C++"  :-)

Zoppo's point is that can only be done in a MFC program, and this certaily is not.  (Spock out.)
Todd, you quoted me yet attributed to Binder.

My suggestion was to use dynamic_cast<>, something *not* suggested before.  Adding the Polymorphic Base Class is safe (if you have access to the source) because it contains nothing except a virtual dtor.

If source is not available (which I doubt) a similar solution can be made, see below.

Zoppo's point was that captainkirk relied on MFC-specific features to answer a question in a C++ forum.

Now, a solution when source for the classes is not available is trickier - you wrap the classes in some of your own and use the wrappers instead (I used structs to save typing):

Given two classes that we cannot change:

    struct SomeThing
    {
        void DoThis() { cout << "Something::DoThis()" << endl; };
    };

    struct AnotherThing
    {
        void DoThat() { cout << "AnotherThing::DoThat()" << endl; };
    };

We create a polymorphic hierarchy of wrapper classes:
(I used inheritance, containment also works)

    struct BaseWrapper
    {
        virtual void Do() = 0;
    };

    struct SomeThingWrapper: BaseWrapper, SomeThing
    {
        virtual void Do() { SomeThing::DoThis(); };
    };

    struct AnotherThingWrapper: BaseWrapper, AnotherThing
    {
        virtual void Do() { AnotherThing::DoThat(); };
    };

Given same array of pointers:

    const int size = 2;
    Base* p[size];
    p[0] = new CMyClass;
    p[1] = new CYourClass;

The fun part becomes trivial:

    for (int i = 0; i < size; ++i)
        p[i]->Do();

Can't go wrong...  Oh, don't forget to delete what you new'ed!

>> Todd, you quoted me yet attributed to Binder.
That is pretty much what Binder was suggesting (i.e. placing all the classes in a hierarchy), although he was not suggesting using dynamic casting, which is certainly an improvement.  My point was just that if this is not possible--because the classes are not ones you've written there are ways, just not good ones.

>> that can only be done in a MFC program, and
>> this certaily is not.
I was thinking this was a BCB program, since he is coming from Delphi and using a syntax that BCB uses frequently, but it isn't BCB, it is VC, so it could be an MFC program, my mistake.
I'll summarize:

1) If you can control the classes, put them in a hierarchy and use dynamic_cast<> for safety.

2) Otherwise, if you can change the program, wrap the classes in a hierarchy and either use dynamic dispatch (virtual forwarding functions) or dynamic_cast<> as in (1).

3) Otherwise, if you only have access to a limited part of the source, switch on your control variable and static_cast<> from a void* to the needed type.

(1) and (2) are safe, (3) is not.
agreed.
Hypo?
Avatar of Hypo

ASKER

Thanks everyone!
you have helped me solve my problem.

I'll just have to find out who the first one was to answer this quizz...!
What method did you eventually decide to use?
Avatar of Hypo

ASKER

Since Nietod posted a working example first, I say it's his points...
(Alexo's comment about Dynamic_Cast works fine too!)

I thank you all for your help!
My code was an alternative to be used in "less desirable" situations.  is that what you used?  (Note it may be the best solution for your case, but if not, the other solutions would be better.  However we don't knw enough abotu what yout are doing to know.  What are these objects you are dealing with?  Are they part of a class heirarchy?
Hypo, tell us which method you decided to use so we may comment.
Avatar of Hypo

ASKER

I used the method nietod proposed, because the pointers in the list are not all part of the same Heirarchy.