"dynamic_cast" with instance of an abstract class ?!?

T

tthunder

Hi @all,

I've got an interesting problem.

These are my classes:

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

class fooBase
{
virtual func();
}

class fooA : public fooBase
{
virtual func();
};

class fooB : public fooBase
{
virtual func1() = 0;
virtual func2();
};

class fooB2 : public fooB
{
virtual func1();
}

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

// Template class
class myFooBase
{
fooBase *m_pPtr;
};

template <class T>
class myFoo : public myFooBase
{
public:

myFoo(fooBase *p_pPtr) :
m_pPtr(p_pPtr)
{
}

bool isCompatible(myFoo *p_p)
{
// Check, if p_p is compatible (dynamic_castable) to T

// Possible way:
T *TempPtr = new T();
if (dynamic_cast<T *> (p_p->m_pPtr))
}
};

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

int main()
{
fooB2 *TEST1 = new fooB2();

myFoo<fooB2> test1(dynamic_cast<fooBase *>(new fooB2()));
myFoo<fooBase> test2(dynamic_cast<fooBase *>(new fooBase()));

// Test: OK
test2.isCompatible(&test1);

// Cannot create, because of new T() => fooB is an abstract class
myFoo<fooB> test3(dynamic_cast<fooBase *>(new fooB3()))
}
 
P

Paul Groke

// Template class
class myFooBase
{
fooBase *m_pPtr;
};

template <class T>
class myFoo : public myFooBase
{
public:

myFoo(fooBase *p_pPtr) :
m_pPtr(p_pPtr)
{
}

bool isCompatible(myFoo *p_p)
{
// Check, if p_p is compatible (dynamic_castable) to T

// Possible way:
T *TempPtr = new T();
if (dynamic_cast<T *> (p_p->m_pPtr))
}
};

Why do you want to leak memory? Why "new T()"? The
"if dynamic_cast<>()" alone will do just fine. BTW: if you
just write "myFoo *p_p" in the parameter list it actually
means "myFoo<T> *p_p" - i.e. if you only assign Ts (or derived)
to "m_pPtr" it will always be compatible!
I think what you're trying to do would read something like:

// inside template <class T> class myFoo ...:
template<class U>
bool isCompatible( myFoo<U> const & other )
{
return !! dynamic_cast<T*>(other.m_pPtr);
}
 
T

tthunder

How to use typeid to check if a class A is the same or a derivation of
class B?

I have explained my problem wrong... I'm sorry for my bad English!

I have a better example:

template <class A, class B>
bool testDerivation()
{
// check, if A is the same or a derivation of class B

// typeid(A) == typeid(B) would be possible.... but only for
Equality... what about derivation?
}

How, to implement such a function?
As I said, I cannot use dynamic_cast, because B (or A) can be abstract.
Because of this I cannot create an instance.
 
J

Jan Meskens

You can also put dynamic_cast within an if/else structure.

eg for testing if a baseClassInstance is 'castable' to a CDerivedClass
type :
if(CDerivedClass* der == dynamic_cast<CDerivedClass*>(baseClassInstance)){
der->doSomething();
}
else if(/*testing to other type*/){
}

//and so on...


Jan
 
T

tthunder

My code is terribly wrong!!!! When I was constructing my code, I was
sleeping...
Normally I can use dynamic_cast<> perfectly...

I have a template class with a pointer

template <class T>
T *myVar;

Now I want to know (in runtime), if this T is for example an base class
of XYZ...

template <class XYZ>
XYZ *myVar2;

BUT... I cannot use dynamic_cast for this... Because dynamic_cast needs
myVar! I want to use T...

Ohhhhh, my English... sorry for that... nobody knows what I want to do?
 
P

Paul Groke

My code is terribly wrong!!!! When I was constructing my code, I was
sleeping...
Normally I can use dynamic_cast<> perfectly...

I have a template class with a pointer

template <class T>
T *myVar;

Now I want to know (in runtime), if this T is for example an base class
of XYZ...

template <class XYZ>
XYZ *myVar2;

BUT... I cannot use dynamic_cast for this... Because dynamic_cast needs
myVar! I want to use T...

Ohhhhh, my English... sorry for that... nobody knows what I want to do?

T and XYZ are both static types, so where's the runtime thing?
This is really starting to confuse me. Why don't you just tell us what
you are trying to do, and why (=what do you need this functionality for)
and maybe we can find a solution.
 
T

tthunder

Ok... what follows now is not exactly what I want to do. But if anyone
can solve this problem, I can solve my own problem!

I have two class types: class A and B. The exact type of those are
defined in a template: e.g. template <class A>, template<class B>

Now I want to know, if A is a derivation of B!
Of course I could use dynamic_cast<>.....
Normally I could use dynamic_cast and one instances: A* classA = new
A(); dynamic_cast<B *>(classA) etc.
BUT I cannot of an instance for an abstract class... "Aabstract* classA
= new Aabstract()" fails...
 
R

Ralph D. Ungermann

Ok... what follows now is not exactly what I want to do. But if anyone
can solve this problem, I can solve my own problem!
I have two class types: class A and B. The exact type of those are
defined in a template: e.g. template <class A>, template<class B>

Now I want to know, if A is a derivation of B!

Since std::type_info offers no way to check the hierarchy, and nobody
else provided a good answer yet, I suppose, that this can't be done in
general.


But I cannot imagine, what the following is good for:

template <class A, class B>
void f()
{
if ( typeid(A).has_base(typeid(B)) ) // fictitious!
{
// you can't create an A or B (might be abstract)
// you can't convert an A (B might be a private base)
}
else
{
// A might otherwise be perfectly convertible to B anyway
}
}

Can you name a single C++ statement, that is guaranteed to work in one
case, but might fail in the other case? I don't see one.


Why don't you just post your *real* problem?


Ralph
 
A

Alf P. Steinbach

* Ralph D. Ungermann:
* (e-mail address removed):
Now I want to know [presumably at compile time], if A is a
derivation of B!

Since std::type_info offers no way to check the hierarchy, and nobody
else provided a good answer yet, I suppose, that this can't be done in
general.

Andrei Alexandrescu presented one solution to this problem in his "Modern
C++ Design". It's based on having a function with one overload that
accepts a B, and one that accepts anything else. Then you pseudo-call it
(within a sizeof-expression) with an A, and check which one is selected.
 
P

Paul Groke

Alf said:
* Ralph D. Ungermann:
* (e-mail address removed):
Now I want to know [presumably at compile time], if A is a
derivation of B!

Since std::type_info offers no way to check the hierarchy, and nobody
else provided a good answer yet, I suppose, that this can't be done in
general.


Andrei Alexandrescu presented one solution to this problem in his "Modern
C++ Design". It's based on having a function with one overload that
accepts a B, and one that accepts anything else. Then you pseudo-call it
(within a sizeof-expression) with an A, and check which one is selected.

Well, I was just confused about the talk about a runtime solution. If
both types are known at compile time, and both types are complete,
then you can use Boost.Type_Traits.

http://www.boost.org/libs/type_traits/index.html

Look for "is_base_and_derived". The only problem is, it will detect
if there exists a "base-berived" relationship between the two classes,
and it will report "true" even if the base type is not accessible
(protected/private inheritance) or if the cast is ambiguous (multiple
"base" are reachable from "derived"). In both cases a cast would fail
to compile - or in case of a dynamic cast maybe compile but fail at
runtime.

But there is also a "is_convertible<T,U>" template that will detect if
a "T" is convertible to an "U". To check if an implicit pointer
conversion is possible just feed in the pointer types, i.e.
"boost::is_convertible<A*,B*>::value" will tell in your case.

The boost implementation of "is_convertible" is actually based on
Alexandrescu's design. And it should work right out of the box with
the majority of compilers.
 
A

Alf P. Steinbach

* Paul Groke:
Alf said:
* Ralph D. Ungermann:
* (e-mail address removed):

Now I want to know [presumably at compile time], if A is a
derivation of B!

Since std::type_info offers no way to check the hierarchy, and nobody
else provided a good answer yet, I suppose, that this can't be done in
general.


Andrei Alexandrescu presented one solution to this problem in his "Modern
C++ Design". It's based on having a function with one overload that
accepts a B, and one that accepts anything else. Then you pseudo-call it
(within a sizeof-expression) with an A, and check which one is selected.

Well, I was just confused about the talk about a runtime solution.

Uhm. If the types are known at all at run-time, then it can be done at
run-time, e.g. a dynamic_cast. If the types are unknown at run-time, i.e.
non-polymorphic objects used polymorphically, then the design is incorrect.

[snipped good references to Boost; the OP might also consider Loki]
 
P

Paul Groke

Alf said:
* Paul Groke:
Alf said:
* Ralph D. Ungermann:


* (e-mail address removed):


Now I want to know [presumably at compile time], if A is a
derivation of B!

Since std::type_info offers no way to check the hierarchy, and nobody
else provided a good answer yet, I suppose, that this can't be done in
general.


Andrei Alexandrescu presented one solution to this problem in his "Modern
C++ Design". It's based on having a function with one overload that
accepts a B, and one that accepts anything else. Then you pseudo-call it
(within a sizeof-expression) with an A, and check which one is selected.

Well, I was just confused about the talk about a runtime solution.


Uhm. If the types are known at all at run-time, then it can be done at
run-time, e.g. a dynamic_cast. If the types are unknown at run-time, i.e.
non-polymorphic objects used polymorphically, then the design is incorrect.

[snipped good references to Boost; the OP might also consider Loki]

Since the "is_convertible" is a problem that can be dealt with at
compile-time I was assuming that maybe the problem was something
different. I have to say I didn't fully understand what exactly the
OP wanted to do until his last posting.
 
T

tthunder

I want to check, if one type is a derivation of another type!
I cannot use dynamic_cast, because I cannot create an instance of one
of these types (abstract).
Why want I do this at run-time? I have to detect errors which I made
when programming...
 
A

Alf P. Steinbach

* (e-mail address removed):
I want to check, if one type is a derivation of another type!
I cannot use dynamic_cast, because I cannot create an instance of one
of these types (abstract).
Why want I do this at run-time? I have to detect errors which I made
when programming...

AFAICS solutions have been presented for all possible scenarios.

Perhaps if you could post a minimal real example.

Your earlier code snippets were not valid C++, and the explanations
didn't make sense.
 
T

tthunder

Please check this code:
(Now it is a very good example)

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

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

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

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

class bad1
{
.....
};

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

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

template <class T>
class Checker : public Base
{
public:
T* ptr;

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 (Checker *checker = dynamic_cast<Checker *>(&base))
{
if (dynamic_cast<T *> (checker->ptr))
return true;
}
return false;
----
}
};


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 - a
temporary instance cannot be created, because T can always be a
abstract class)
 
A

Alf P. Steinbach

* (e-mail address removed):
template <class T>
class Checker : public Base
{
public:
T* ptr;

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 (Checker *checker = dynamic_cast<Checker *>(&base))
{
if (dynamic_cast<T *> (checker->ptr))

This inner 'if' is equivalent to

if( checker->ptr != 0 )

because it casts a T* pointer to the very same type T*.
 
T

tthunder

Of course you are right....
another example

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

class 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 - a

temporary instance cannot be created, because T can always be a
abstract class)
 
A

Alf P. Steinbach

* (e-mail address removed):
Of course you are right....
another example

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

class 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;

This shouldn't compile because class 'c' isn't polymorphic.

Tested: it doesn't compile (when typos corrected in the rest of
code) using MSVC 7.1.

If the problem is to _only_ add some code in here that does "the right
thing", then that's impossible because 'c' isn't polymorphic. However,
you can add code elsewhere that retains type information. The easiest
would be to make class 'c' polymorphic by adding a virtual destructor,
and then write, here,

return (dynamic_cast<T*>( base.ptr ) != 0);

I don't understand your comment about the pointer being 0.

If the pointer is zero then it isn't pointing to anything: which result,
if any, would you like in that case?
 
T

tthunder

You are right... the pointer does not point to anything! I know that
dynamic_cast does not work here! I know, that it return NULL, which is
the only right value! I know that there is another intention..

The result I need is different and simple: I do not need a pointer!!!!
I need BOOL! Is castable or is not castable! Of course I know, that a
NULL pointer is never castable. But my question: would it be castable
if there will be a value in it!

By the way: My Compiler (BCB 5.0) compiles the code... I only had to
correct syntax errors and implement "virtual ~c() {}" in class c.
Without dynamic_cast would not work!
But I say it again: dynamic_cast is NOT what I need.
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top