• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 273
  • Last Modified:

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;
0
Hypo
Asked:
Hypo
  • 6
  • 6
  • 4
  • +5
1 Solution
 
yonatCommented:
PointerToALabel->Caption = "1";
0
 
ch52jbCommented:
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.
0
 
HypoAuthor Commented:
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?
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
BinderCommented:
  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();

0
 
nietodCommented:
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.


0
 
nietodCommented:
A C-style cast is doen by placing the desired data type in parentheses before the value to be converted, like

double D;
int X = (int) D;

converts the double value D to an int.

Now this only compiles if the compiler is able to make the conversion.  It can convert between the built-in types, like double, int, char etc.

There is another type of conversion that the compile can do, and that is conversion of pointers. (Actually there are times when it can't do this.)  It can convert a point to 1 type of data to a pointer to a 2nd type of data.  This always succeeds in that it will always compile.  But it might not work correctly when it runs.  You must be sure that the type of conversion is really safe to do and justified, like in the example above.
0
 
alexoCommented:
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...
0
 
captainkirkCommented:
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()
0
 
ZoppoCommented:
captainkirk, that's MFC and not C++ ...

ZOPPO
0
 
nietodCommented:
>> 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.)
0
 
alexoCommented:
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!

0
 
nietodCommented:
>> 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.
0
 
alexoCommented:
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.
0
 
nietodCommented:
agreed.
0
 
alexoCommented:
Hypo?
0
 
HypoAuthor Commented:
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...!
0
 
alexoCommented:
What method did you eventually decide to use?
0
 
HypoAuthor Commented:
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!
0
 
nietodCommented:
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?
0
 
alexoCommented:
Hypo, tell us which method you decided to use so we may comment.
0
 
HypoAuthor Commented:
I used the method nietod proposed, because the pointers in the list are not all part of the same Heirarchy.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 6
  • 6
  • 4
  • +5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now