Click to See Complete Forum and Search --> : How to identify the validity of a class pointer
anand_gore
May 17th, 1999, 12:22 AM
Suppose i have written a function called fun takes a parameter which is a pointer to a class object a.
here is the code
/code
bool void fun(a *ptr)
{
// here i want to check the validity of the pointer
}
I want to check the validity of the pointer.That means i want to check wheather the object is pointing to the correct class or its subclass's object or not.
Please let me know
Thanks
Anand
Martin Speiser
May 17th, 1999, 03:34 AM
Hi Anand,
if your class a is inherited from CObject and declared with DECLARE_SERIAL or DECLARE_DYNAMIC you can get type information with the member function IsKindOf.
Martin
anand_gore
May 17th, 1999, 04:46 AM
Thanks Martin...
Better if i explain the senario to you....
See I may be using the Borland compiler which my not support the MFC's ok?
secodly if i pass a pointer to object which is a derived class of the class which is used as a parameter type.then again there may lie a problem...
Ok
I will show a sample code here..
/code
class first
{
// data members and functions and virtual of class first
};
class second:public first
{
// data members and functions and virtual of class second
}
main()
{
first *f;
f = new second;
if(fun(f))
printf("Valid pointer");
else
printf("Invalid pointer");
delete f;
if(fun(f))
printf("Valid pointer");
else
printf("Invalid pointer");
}
bool fun(first *one)
{
// here the checking will lie...if the pointer pointing to proper objects it will return true else false..
}
here in above example first fun call will return true and second will return false..
Can this be done....
I want the implementation of the function fun...
Please help
Bye
Anand
Martin Speiser
May 17th, 1999, 06:04 AM
Sorry, I don't know anything about the Borland compiler. There is an ANSI standard now for RTTI, but I don't know whether Borland has implemented it.
Martin
Albert
May 17th, 1999, 07:44 AM
It looks like you've actually got two issues, here.
The first is determining whether a class is in the proper hierarchy, or not; that is, whether it is derived from a specific (known) base class. Not being familiar with Borland's products (any longer), I can only recommend RTTI and the dynamic_cast operator for this:
In your example:
First* p = dynamic_cast<Second* somePointer>
should return a non-NULL result, whereas
First* p = dynamic_cast<SomeUnrelatedClass* somePointer>
should return NULL.
Because RTTI consumes runtime resources, most vendors do not enable it by default. You must do so. I think that if RTTI is not enabled or supported, dynamic_cast gets demoted to static_cast, which won't really help you with this problem.
The other issue you face is how to detect when an object has been deleted. You can do this (if Borland doesn't already) by overloading ::delete. You'd overload ::delete to overwrite the memory occupied by the destroyed object with some marker pattern, and then your validator method could check for this. Microsoft does this with debug versions of their operators (you probably don't want to do this in the release code because of the performance hit).
You could also define a macro, called DELETE, like this:
#define DELETE(p) delete (p); (p) = NULL;
Then your validator simply checks for a NULL pointer. Some operating systems (like Windows) will even generate a GPF on an attempt to dereference a NULL pointer, which can be a good thing in this kind of situation...
Hope this helps.
Paul Beyard
Dave Lorde
May 17th, 1999, 08:31 AM
There are two different issues involved with the kind of validity checks on pointers you require.
The first issue is whether the pointer is a valid pointer (does it actually point to an object?). This is left up to the programmer. The language doesn't provide any useful tools for this. A pointer isn't given a value unless you provide one, so by default they have whatever value was already in the memory where they are created - effectively random. You must always ensure that pointers either point to objects or are null (have the value 0). This way you can tell whether a pointer is pointing to an instance by comparing it with 0. This means *always* initialising pointers:
char* foo; // No, this is asking for trouble!
char* bar = 0; // Yes, we can tell it's not pointing at an object
char* paf = new char[5]; // Yes, we can tell it's pointing at an object
With that last example, there is the problem of what to do with the pointer after it's been deleted, when it no longer points to a valid instance (the pointer value doesn't change, but the object pointed to is no longer there). At this point, the it is just like an uninitialised pointer, so it must be given a value immediately:
delete[] paf; // pointer value now meaningless
paf = 0; // OK, pointer value now clearly null
My own preference is to combine them into a single expression statement:
delete[] paf, paf = 0; // No danger of inserting something between them
The 'delete' function is written with this convention in mind; it is perfectly safe to delete a null pointer (it's just ignored):
delete[] paf, paf = 0;
delete[] paf; // OK, safe as houses
However, deleting an uninitialised pointer or one that is deleted but not nulled, will almost certainly crash your program!
Anyway, when creating objects using dynamic memory with 'new', it's much simpler and safer to use smart pointers like std::auto_ptr.
The second issue is, if the object pointed to is valid, what type is it?
Here the language provides two related ways to tell, run-time typing (RTTI), and dynamic casting.
Dynamic casting is most common, and uses RTTI to cast from one pointer or reference to a type in an inheritance hierarchy, to another. If the cast is not valid, it will return 0.
bool func(Base* pBase)
{
Derived* pDerived = dynamic_cast<Derived*>(pBase);
if (pDerived == 0)
return false; // pBase does not point to an instance of Derived
... // continue using pDerived
}
Often, good design can avoid this kind of run-time checking by appropriate use of virtual functions in the Base/Derived classes, or use of the Visitor pattern, etc.
If you really want to know the exact type of an object, use the typeid() operator which returns a type_info object. I've never needed this yet!
Hope this helps,
Dave
Dave Lorde
May 17th, 1999, 09:23 AM
I thought you were playing with my last posting until I saw yours was posted first!
Synchronicity...
Dave
anand_gore
May 17th, 1999, 10:55 PM
Okay I think i will be more clear about this problem....
See I am suppose using the delete operator inside a class coz thats my design...like.....
void first::SomeFunction(void)
{
// some operation done here
delete this;
return;
}
Now see the senario.....My some object pointer must be still pointing to this above class which has deleted it self.Now in the main program i want to check the validity of it...
For like VC programming some class CDialog class must be deleting itself on some users event...
And in main program it still pointing to the same object..
So next time how should i check the validity of it...
Anand
Dave Lorde
May 18th, 1999, 05:16 AM
Why are you using 'delete this', and what is the function that uses it doing?
It is an advanced idiom that should only be used in specific circumstances, and only if you know exactly what you are doing.
I think you've discovered why it can be such a bad idea. You not only need to be certain the object was allocated on the heap before deleting it (which means disabling stack-based construction), but you also need to know when it gets deleted to avoid using an invalid pointer to it.
> So next time how should i check the validity of it...
You can't directly test the validity of a simple pointer to an object that might have deleted itself that way. You must arrange things so it isn't necessary.
I strongly suggest you change your design unless you really need to use 'delete this'. If you want your dynamically allocated objects to be deleted automatically when they are no longer needed, or when they go out of scope, use smart pointers to hold them. A reference-counted smart pointer can delete its object when no longer in use, and a simple auto-pointer will delete its object when it goes out of scope.
See Scott Meyers book "More Effective C++", items 27, 28 and 29.
Dave
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.