Reputation: 93
class file {
std::string name;
};
class directory : public file {
std::vector<file*> entries;
};
directory d;
file f;
f = d; // Only d.name is copied to f; entries are lost
Is it if we do this:
directory* dp = new directory;
file* fp ;
fp = dynamic_cast<file*>(dp);
Keeps entries and identity as a directory object or still only dp->name
is copied to f
; entries are lost.
Also, how does downcast work?
What happens if we do:
dp = dynamic_cast<dp*> (fp);
Upvotes: 1
Views: 19859
Reputation: 41
Here is an explanation on what is up casting and down casting taken from link: questionscompiled.com
Upcasting: Upcast is conversion of pointer or reference of derived class type to pointer or reference of base class type, going up in the inheritance tree. Upcasting helps in achieving interfaces concept in C++. When a function is called on base class type pointer or reference(pointing or referring to some of its derived class), correct member function of that derived class gets invoked.
Downcasting: Downcast is the conversion of pointer or reference of base class type to pointer or reference type of its derived class, going down in the inheritance tree. This is achieved with help of dynamic_cast operator that safely downcast at run time.
Here is an example:
class A
{public:
int i;
virtual void show(){}
};
class B:public A
{
public:
int j;
virtual void show() { cout<<"B"; }
};
int main()
{
A* ptr=new B; // UPCASTING
B* ptrb;
ptrb=dynamic_cast<B*>(ptr); //DOWNCASTING to derived object
ptrb->show(); // upcasting helped in implementing interface
}
With reference to above example, dynamic_cast ensures that ptr points to object of type B or its subclass.
Upvotes: 3
Reputation: 33607
Inheritance captures the relationship "is a". Given the context of your question, the following isn't very sensible:
class directory : public file
Just because both directories and files have names does not mean that a directory "is a" file
. It would also be inappropriate to say that a file "is a" directory
.
There are many other lines of reasoning you might take here. For instance, you could argue that both files and directories are cases of thing_that_has_a_name
:
class thing_that_has_a_name {
std::string name;
/* ... */
};
class file : public thing_that_has_a_name {
/* ... */
};
class directory : public thing_that_has_a_name {
std::vector<file*> entries;
/* ... */
};
(That's one way of going about it, but inheritance is a rather heavy-handed mechanism. If you are creating base classes for things like the abstract concept of "having a name" then you quickly will find yourself needing to inherit from multiple base classes.)
To bring this back to bear upon the technical aspects of what you're looking at, what you have to remember is that there's a big difference between creating new objects vs. interfacing with an existing file or directory object as a thing_that_has_a_name
. If you ever make a declaration like:
directory d;
file f;
These are instantiations. Constructors are run. Whatever the sizeof
a directory is, that's how much memory d
just got. Whatever the sizeof
a file is, that's what f
just got. However:
thing_that_has_a_name& tthan_ref_to_d (d);
thing_that_has_a_name* tthan_ptr_to_f (&f);
These merely create a reference and pointer, respectively, through which you can interact with the directory and file objects through the interface specified in their base class. "Upcasting" like this (called "up" because you're climbing the class hierarchy toward the root) is relatively safe...and not a sign that you're doing things wrong.
On the other hand, "Downcasting" can be dangerous. We know that every directory
and file
can be treated as a thing_that_has_a_name
...yet if you have a pointer or reference to a thing_that_has_a_name
then arbitrary code can't be sure that it's a directory
or file
. There are ways to insert conditional code to check and be sure, but this is often considered a sign that you're doing something wrong in your design:
http://en.wikipedia.org/wiki/Run-time_type_information
Others have provided some more details, so I'll stop here, but just throw it out there in case you find something useful about it.
Upvotes: 2
Reputation: 258618
I'll try to explain simply, but you should still read more documentation on this.
directory d;
file f;
f = d; // Only d.name is copied to f; entries are lost
This is because directory and file are of different types and sizes. File has size sizeof(file)
and directory sizeof(directory)
, which is greater than sizeof(file)
. Even a raw memory copy would only copy the file part of directory to the file object or give undefined behavior if you intended to copy more.
directory* dp = new directory;
file* fp ;
fp = dynamic_cast<file*>(dp);
First off, dynamic cast won't work here since these are not polymorphic types. If it did, these are just pointers. Since directory is-a
file, you can point to a directory using a file pointer. The object is at that respective location. But you don't have access to exclusive directory members via the file pointer, unless you cast back.
dp = dynamic_cast<dp*> (fp);
You're regaining directory member access to your original pointer, as explained above.
Upvotes: 3