Domanda

I am moving to cpp from java, and I have a little problem understanding how some cpp features work. When we use polymorphism or type-safe casting, cpp needs to know the exact type of the object. In java, every object had a link to its defining class and so this information could be retrieved. But in cpp that's not the case (I think), I'm saying that because the sizeof() operator returns no more than what the object fields occupy and thus I'm guessing that's not where the type information is stored. Am I mistaken here? If no then how does cpp manage polymorphism and stuff?

È stato utile?

Soluzione

C++ is only capable of performing dynamic type introspection on types that have virtual methods; unlike in Java, C++ methods are non-virtual by default.

The (usual) result of adding virtual methods to a class is that the compiler emits an additional, hidden slot in the class structure containing a pointer to a vtable; the vtable contains slots for method pointers for the virtual methods and an additional pointer to dynamic type information. The vtable is used in the following ways:

  • Invoking virtual methods on an instance will follow the vtable and call through the appropriate vtable method slot;
  • Calling typeid on an instance of a class with virtual methods will follow the vtable pointer to the dynamic type information determine the actual (dynamic) type of the instance;
  • Calling dynamic_cast on an instance of a class with virtual methods will follow the vtable pointer to the dynamic type information and use that to adjust the instance pointer; this is necessary because C++ allows multiple inheritance so pointers of different type to the same object may point to different locations in memory.

The pointer-to-vtable slot means that if a class (or its base classes) has virtual methods, then sizeof will be greater than sum of the object member fields.

Altri suggerimenti

C++ polymorphism is limited to virtual functions. All that's necessary to implement virtual functions is a table of function pointers common to a class, commonly known as a vtable. A pointer to the vtable will be added to each object, but the vtable itself is common to all objects of the same class.

Note that the use of a vtable is not mandated by the C++ standard but is nearly universal in practice.

In C++ it is a good practice not to use RTTI, you can write really large applications without using it. You should know types of your objects, and cast them to appropriate types. In Java you could use if ( obj instanceof ClassA ) {}, but in C++ you want see such code, even tho it can be writeen.

You are asking about reflection, and no, C++ does not have it, and that it doesn't is intentional. Stroustrop saw those other languages where objects were constant querying one another with "what are you" kinds of messages as a sign of something broken. By accident, there is a limited amount of reflection that can be gained through metaprogramming.

There is a way to sneak around the lack of reflection in C++. Dynamic casting to a void* gives a pointer to the most derived object. So now you just have to make sense of that pointer. You can do this if you have your own type management system. It's not simple, it almost inevitably breaks the rules of the language somewhere, but it is used quite often for checkpoint/restart purposes.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top