views:

410

answers:

5

Are there any cases where we do down casting of objects?

If we do, why?

I have observed a way of hiding implementation using the below code. Is this the correct way to do? Is there any better way to achieve the same.

class A{
    public:
      A();
      virtual ~A();
      //exposed virtual functions
};

class AImpl : public A{
    public:
       AImpl(A *obj);
       virtual ~AImpl();     
      //exposed virtual functions++
};

class Helper{ //utility class so i am making constructor and assignment operator as private
    public:
       static bool doWork(A *obj){
          AImpl *objImpl = dynamic_cast<AImpl *> (obj);
          return doWork(objImpl); // some internal function
       }

    private:
         Helper();
         Helper(const Helper& obj);
         const Helper& operator=(const Helper& obj);
};

The question still does not makes sense. I agree. I still have not figured out a proper way of hiding the implementation details from the client.

UncleBens I termed this thing wrongly as Object slicing. Basically, I was referring to this (Object Slicing) as the information related to derived part is missing.

S.Soni Thanks for giving a wonderful explaination. Now, I can really put forward question.

Consider a clients perspective. The only class which are visible to him is class A and the Helper class (because I have hidden implementation behind AImpl

Client has to write the following code as he is unaware of AImpl class

int main(){
    A *a = new A();
    Helper.doWork(a);
    // ...
}

As you said AImpl * in this case will actually be pointing to the base class object, which is wrong (you have explained it with a great example), so this approach of hiding implementation is not correct.

Any attempt to access a derived class member function will result in a crash (and correctly so).

How should I go about hiding the implementation in this case? This is a design problem now?

+1  A: 

Your example code contains at least 4 syntax errors, so it's hard to judge what you're trying to do.

And it logically won't work either. You have a class AImpl that inherits A, then a member function that takes an A and appears to try to dynamic-cast it to an AImpl. But it isn't an AImpl, because it's just an A, as that is how the parameter is declared. If you were to pass an instance of AImpl to that function, it would be sliced down to just an A.

You could make it a reference or pointer to an A, and then it could be an AImpl. Dynamic casts are only ever of use on references or pointers.

Down-casting is used when we have a variable or parameter that has the static type of a base class but we logically know that it is (or might be) of a derived class. It is avoided wherever possible because it means that the compilation process is not able to completely check the type-correctness of the program, i.e. the answer to the question "are you trying to put a square peg into a round hole" cannot be fully answered until runtime.

Update after question was edited

It sounds like you want clients of your library to have access to a limited interface to an object, A, but when they pass it to a function in your library you will have access to the full interface. You could just use friend for this.

class A
{
    friend class LibraryThing;

    void visibleToLibraryThing();

public:
    // ctor, etc.

    void visibleToAll();
};

class LibraryThing
{
public:
    void foo(A &a)
    {
        a.visibleToLibraryThing();
    }
};

The LibraryThing class can access the private members of A, because it is declared as a friend of A.

The downside is that LibraryThing can access everything in A, so it means that as the author of the library, you won't be able to benefit from encapsulation. Only users of your library will.

Daniel Earwicker
You are so quick. I have made the corrections.Basically I am trying to hide class AImpl using dynamic_castSee, if the code now makes sense to you.
Devil Jin
+2  A: 
**Are there any cases where we do down casting of objects**

The purpose of dynamic_cast is to perform casts on polymorphic types. For example, given two polymorphic classes Band D, with D derived from B, a dynamic_cast can always cast a D* pointer into a B* pointer. This is because a base pointer can always point to a derived object. But a dynamic_cast can cast a B* pointer into a D* pointer only if the object being pointed to actually is a D object.

**`Is there any better way to achieve the same`**

Perhaps the most important of the new casting operators is dynamic_cast. The dynamic_cast performs a run-time cast that verifies the validity of a cast.

1) Your class is not polymorphic.A class that declares or inherits a virtual function is called a polymorphic class

2) Syntax of dynamic_cast is dynamic__cast (expr)

1st Edit :

Try like this , it will work

class A
{
    public:
      A();
      virtual ~A();// Notice here i have put virtual
};

class AImpl : public A
{
    public:
       AImpl(A *obj);
       ~AImpl();     
};

class Helper
{
    public:
     Helper(){}
       static bool doWork(A *obj)
       {
          AImpl *objImpl = dynamic_cast<AImpl*> (obj);
          return true;
       }
};

Study this example :

class Base
{
public:
    virtual void f() { cout << "Inside Base\n"; }
    // ...
};
class Derived: public Base 
{
public:
    void f() { cout << "Inside Derived\n"; }
};


int main()
{  
    Base *bp, b_ob;
    Derived *dp, d_ob;
    dp = dynamic_cast<Derived *> (&d_ob);
    if(dp) {
     cout << "Cast from Derived * to Derived * OK.\n";
     dp->f();
    } else

     cout << "Error\n";
    cout << endl;
    bp = dynamic_cast<Base *> (&d_ob);
    if(bp) {
     cout << "Cast from Derived * to Base * OK.\n";
     bp->f();
    } else
     cout << "Error\n";
    cout << endl;
    bp = dynamic_cast<Base *> (&b_ob);
    if(bp) {
     cout << "Cast from Base * to Base * OK.\n";
     bp->f();
    } else
     cout << "Error\n";
    cout << endl;
    dp = dynamic_cast<Derived *> (&b_ob);
    if(dp)
     cout << "Error\n";
    else
     cout << "Cast from Base * to Derived * not OK.\n";
    cout << endl;
    bp = &d_ob; // bp points to Derived object
    dp = dynamic_cast<Derived *> (bp);
    if(dp) {
     cout << "Casting bp to a Derived * OK\n" <<
      "because bp is really pointing\n" <<
      "to a Derived object.\n";
     dp->f();
    } else
     cout << "Error\n";
    cout << endl;
    bp = &b_ob; // bp points to Base object
    dp = dynamic_cast<Derived *> (bp);
    if(dp)
     cout << "Error";
    else {
     cout << "Now casting bp to a Derived *\n" <<
      "is not OK because bp is really \n" <<
      "pointing to a Base object.\n";
    }
    cout << endl;
    dp = &d_ob; // dp points to Derived object
    bp = dynamic_cast<Base *> (dp);
    if(bp) {
     cout << "Casting dp to a Base * is OK.\n";
     bp->f();
    } else
     cout << "Error\n";
    return 0;
}
sat
"dynamic_cast can cast a B* pointer into a D* pointer only if the object being pointed to actually is a D object"Can you explain this using an example. In the example I quoted above I am trying to cast a A* pointer to AImpl* pointer which is actually a A object. so, according to you this is wrong.What approach should i be using in the case above. (Hope I have been able to make you understand my problem)
Devil Jin
+1 for a great piece of explaination. Thanks
Devil Jin
+1  A: 

From your code and the information that the passed in pointer actually points to an A, and not an AImpl, also the constructor AImpl that accepts an A*, I gather that what you want it:

class Helper{
    public:
       static bool doWork(A *obj){
          AImpl objImpl(obj); //construct an AImpl instance, using available constructor
          return doWork(&objImpl); // some internal function
       }
};

There is no way to cast a base instance into an instance of a derived class (where would the missing derived part come from??).

UncleBens
correct advice, but question has been modified in the meantime...
gimpf
yes! i am trying to clarify my doubts here. sometimes i feel myself in the middle of so much confusion... that I find hard to explain my question itself.
Devil Jin
+1  A: 

Well, if the following holds true (not the only valid reasons, but a common one):

  • you have a MVC like architecture
  • you want to hide the implementation details from client code (no-na...)
  • you need to pass some references from core to client-code (handles of all sorts, etc.)
  • the only valid implementation of the public interfaces must be in the core of the MVC part

then using this way is quite common.

However, if it is simply not allowed to use any other implementation (because only your library core may implement the interface), then asserting the type would be nice too; this would provide a nice landing in the debugger or crash-dump for any user of the library who messed with it in a way it should not be done. Of course, the documentation should clearly indicate that deriving from A is a bad idea.

gimpf
A: 

You can use PIMPL to hide implementation details, mask dependencies, and speed up builds.

http://www.gotw.ca/gotw/028.htm

http://www.ddj.com/cpp/205918714

http://www.gotw.ca/gotw/024.htm

joshperry