Is this ok to do or have i forgot my manners?Thank you

struct A  {
   virtual A* func()=0;
 };

template <typename T=int>
struct B : public A  {
   A* func ()  {
      return this;
    }
 };

typedef B<> B_int;
typedef B<float> B_float;

struct C : public B_int  {
   A* func ()  {
      return this;
    }
 };

Recommended Answers

All 6 Replies

What exactly are you asking?

I just wanted a general opinion on the upcasting from a C* to an A* since A isn't the direct parent of C.It doesn't seem right even if the implementation behaves as expected in my program.Is this a sign of bad practice?

It's totally fine. In fact, it is a safe way to do it. But it is kinda useless as is, because if the caller has access to the vtable pointer (to look up the virtual call to func()), then it can also implicitly cast the object pointer or reference to a pointer or reference to the base class A. Also, overriding the func() in class C is useless because the implementation in class B is already sufficient and can be reused.

Nevertheless, a very similar technique can be used to perform downcasts (to substitute for the dynamic_cast operator). This is a classic example:

struct A  {
   static const int myID = 1;
   virtual void* func(int aID) { 
     if(myID == aID)
       return this;
     else
       return NULL; 
   };
 };

struct B : public A  {
   static const int myID = 2;
   void* func(int aID) { 
     if(myID == aID)
       return this;
     else
       return A::func(aID); 
   };
 };

struct C : public B  {
   static const int myID = 3;
   void* func(int aID) { 
     if(myID == aID)
       return this;
     else
       return B::func(aID); 
   };
 };

template <typename T, typename U>
T* my_dynamic_ptr_cast(U* obj) {
  return reinterpred_cast<T*>(obj->func(T::myID));
};

int main() {
  C objC;
  A* ptrA = &objC;
  C* ptrC = my_dynamic_ptr_cast<C>(ptrA); //downcast of a pointer to A to a ptr to C.
  std::cout << "Pointers are: " << ptrC << " " << &objC << std::endl;
  return 0;
};

Thank you very much Mike.Since you say it's ok i can't trust more in one's answer.What you proposed is exactly what i was implementing though i'm trying to match window handles instead of Ids.I noticed you are using reinterpret_cast so am i to use an explicit cast for upcasting or will the implicit cast suffice?

In the snippet I showed, I made a mistake, it should be static_cast and not reinterpret_cast (sorry), to turn a void* into a T* properly. That is also a _downcast_ (because void* is an implicit base pointer type for all pointer types in C++, that's inherited from C). In practice, a reinterpret_cast also works equally (but is technically not guaranteed to work the same, based on the standard).

>>am i to use an explicit cast for upcasting or will the implicit cast suffice?

Upcasting pointers is always implicitly done and there is no need to use a static_cast operator to do so. But, of course, you can always use a static_cast just for making it obvious that a cast is made (instead of hiding it in an implicit cast). But, of course, it makes no difference in execution.

One very important rule: Do not use a "reinterpret_cast" to do an upcast or a downcast of pointers between two non-void types (even if they are related in a hierarchy). There is a big difference between reinterpret_cast and static_cast, they should not be confused. In my example, it is ok because the pointer returned by the func() function was just cast from T* to void*, so it is safe to cast it back to T*. This is the only acceptable use of reinterpret_cast with pointers, i.e., to temporarily cast a pointer to void* and immediately cast it back to its original type. That is guaranteed to work and is safe. What you cannot do is cast from T* to U* with a reinterpret_cast, this is not safe, regardless of the relation between classes T and U, you need to use static_cast or dynamic_cast (depending on what you want).

Thanks again for the disambiguation.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.