check derivations of pointer types (without dynamic_cast!)

T

tthunder

Hi @all,

Perhaps some of you know my problem, but I had to start a new thread.
The old one started to become very very confusing.
Here clean code (which compiles well with my BCB 6.0 compiler). You can
find a problem there, which cannot be solved by dynamic_cast, because
the pointers can be NULL, and I only want to know, if the pointer type
is derived from another pointer type.
BTW: I cannot create a temporary instance, because used classes can be
abstract (pure virtual functions)...

Here the code:

--------------------


class c
{
virtual ~c() {}
};


class c1 : public c
{
virtual void foo() = 0;
....
};

class c2 : public c1
{
....
};

class c3 : public c2
{
....
};

class bad1 : public c
{
.....
};

--------------------

class Base
{
public:
c *ptr;

virtual ~Base() {}
};


template <class T>
class Checker : public Base
{
public:

bool check(Base &base)
{
---- PSEUDO (with dynamic_cast, which does not work, if
ptr is NULL - a temporary instance cannot be created, because T can
always be a abstract class):
if (dynamic_cast<T *> (base.ptr))
return true;
return false;
----
}
void setPtr(c *p_ptr)
{
ptr = dynamic_cast<T *> (p_ptr);
}
};

main()
{
Checker<c1> checker1;
Checker<c2> checker2;
Checker<c3> checker3;
Checker<bad1> checker4;
checker1.check(checker1); // return true
checker1.check(checker2); // return true
checker1.check(checker3); // return true
checker1.check(checker4); // return false, because bad1 cannot
be casted to c1
}

--------------

Do *****NOT***** use dynamic_cast!!!!!!
Do *****NOT***** use dynamic_cast!!!!!!
Do *****NOT***** use dynamic_cast!!!!!!
Please read the following line in my code:

---- PSEUDO (with dynamic_cast, which does not work, if ptr is NULL)
 
V

Victor Bazarov

Perhaps some of you know my problem, but I had to start a new thread.
The old one started to become very very confusing.
Here clean code (which compiles well with my BCB 6.0 compiler).

I bet you 1000 Euros that it doesn't. I left it in just to show you
that you lied when you said that it was "clean" and "compiled well".
You
can find a problem there, which cannot be solved by dynamic_cast,
because the pointers can be NULL, and I only want to know, if the
pointer type is derived from another pointer type.

See Boost, ::boost::is_base_and_derived<T,U> template.

And you should try to use correct terminology. In C++ there is no
way to "derive a pointer type from another pointer type". There is
a way, however, to derive a type from another type, and to declare
a pointer to it. Yes, I knew what you meant but only because I've
been reading this newsgroup for so long. Next time you explain it
to somebody else, you better do it right.
BTW: I cannot create a temporary instance, because used classes can be
abstract (pure virtual functions)...

Here the code:

--------------------


class c
{
virtual ~c() {}
};


class c1 : public c
{
virtual void foo() = 0;
...
};

class c2 : public c1
{
...
};

class c3 : public c2
{
...
};

class bad1 : public c
{
....
};

--------------------

class Base
{
public:
c *ptr;

virtual ~Base() {}
};


template <class T>
class Checker : public Base
{
public:

bool check(Base &base)
{
---- PSEUDO (with dynamic_cast, which does not work, if
ptr is NULL - a temporary instance cannot be created, because T can
always be a abstract class):
if (dynamic_cast<T *> (base.ptr))
return true;
return false;
----
}
void setPtr(c *p_ptr)
{
ptr = dynamic_cast<T *> (p_ptr);
}
};

main()
{
Checker<c1> checker1;
Checker<c2> checker2;
Checker<c3> checker3;
Checker<bad1> checker4;
checker1.check(checker1); // return true
checker1.check(checker2); // return true
checker1.check(checker3); // return true
checker1.check(checker4); // return false, because bad1 cannot
be casted to c1
}

--------------

Do *****NOT***** use dynamic_cast!!!!!!
Do *****NOT***** use dynamic_cast!!!!!!
Do *****NOT***** use dynamic_cast!!!!!!
Please read the following line in my code:

---- PSEUDO (with dynamic_cast, which does not work, if ptr is NULL)

V
 
V

verec

bool check(Base &base)
{
---- PSEUDO (with dynamic_cast, which does not work, if
ptr is NULL - a temporary instance cannot be created, because T can
always be a abstract class):
if (dynamic_cast<T *> (base.ptr))
return true;
return false;

Your wording is a bit confusing as to where the problem lies.
Is it that dynamic_cast<T *>(x) fails when x is 0 ?

If yes, there's a simple fix:

bool check(Base & b) {
return b.ptr == 0 ? false : dynamic_cast<T *> (b.ptr) ;
}

otherwise, I don't understand the problem :(
 
T

tthunder

::boost::is_base_and_derived<T­,U> does not work in my case!
For this function I need two variable types. I only have one at the
time I want to check them.

If I am in my class "Checker", I have got T, ok! But how to get U?
I only have a reference to Base (which is "Checker", too). I do not
know, if this Base is Checker<c1>, Checker<c2>, Checker<c3>,... I can
try, ok, but this is not what I want to do.
 
T

tthunder

Well, your check is not necessary, because dynamic_cast does return
NULL (FALSE), if ptr is NULL!

But I don't want to return NULL! If the types are derived (or the same)
I want to return TRUE even if ptr is NULL.

It does not matter for me which value is in my ptr, I am only
interested in its type.

And yes again, I know, that dynamic_cast cannot do this! I thought
about things like RTTI, but even there I cannot see functions which can
solve my problem.
 
H

Howard

Hi @all,

Perhaps some of you know my problem, but I had to start a new thread.
The old one started to become very very confusing.
Here clean code (which compiles well with my BCB 6.0 compiler). You can
find a problem there, which cannot be solved by dynamic_cast, because
the pointers can be NULL, and I only want to know, if the pointer type
is derived from another pointer type.
BTW: I cannot create a temporary instance, because used classes can be
abstract (pure virtual functions)...

Here the code:

--------------------


class c
{
virtual ~c() {}
};


class c1 : public c
{
virtual void foo() = 0;
...
};

class c2 : public c1
{
...
};

class c3 : public c2
{
...
};

class bad1 : public c
{
....
};

--------------------

class Base
{
public:
c *ptr;

You have declared ptr as the type c*. You want to know what type it is?
It's type is c*, because that's what it's declared as.
virtual ~Base() {}
};


template <class T>
class Checker : public Base
{
public:

bool check(Base &base)
{
---- PSEUDO (with dynamic_cast, which does not work, if
ptr is NULL - a temporary instance cannot be created, because T can
always be a abstract class):
if (dynamic_cast<T *> (base.ptr))
return true;
return false;
----
}
void setPtr(c *p_ptr)
{
ptr = dynamic_cast<T *> (p_ptr);
}
};

What exactly are you trying to accomplish?

If ptr has been instantiated, then you can use dynamic_cast to verify its
type, right? (Although, I fail to see a need to do so.) And if it's NULL,
then it hasn't been instantiated, so the ONLY thing that can be said about
it is that it's a c* pointer. If that's ok, then return TRUE when ptr is
NULL. If it's not ok, then what exactly do you want?

You code does not show how ptr gets set. There's a setPtr function, but
nothing ever calls it. And there's no constructor shown, so as far as I can
tell, ptr is NEVER set to anything!

Without knowing what it is you're trying to accomplish, we can't give you a
reasonable solution to the problem.

But if all you want to do is find out the type of object pointed to by ptr,
then obviously it's impossible unless it actually DOES point to something,
right? Otherwise, it's simply a NULL pointer of type c*. Given the code
you've shown, that tells you nothing about the type passed as a parameter to
Checker<>. But that's the fault of your code sample which isn't using that
parameter in anything but the check and setPtr functions, as far as I can
tell.

Either fix the example and explain what you're actually trying to
accomplish, or else accept that an uninitialized base class pointer is
simply that, an uninitialized base class pointer, and has no relation
whatsoever to the parameter passed in to the constructor (unless and until
you set up that relationship somehow, such as by instantiating an object for
ptr to point to).

One final thing: if you have a member pointer, chances are you need to
initialize it in the constructor (at least to NULL, if nothing else), plus
you'll likely need to delete it in your base class destructor, and also add
a copy constructor and assignment operator. (See the "rule of three".)

-Howard
 

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

No members online now.

Forum statistics

Threads
473,967
Messages
2,570,148
Members
46,694
Latest member
LetaCadwal

Latest Threads

Top