There is one little related question. But the topic is entirely different.
Now, one concept is about the function resolution and another is about class resolution ? I am wondering that how is it possible if they are using the same vtable (at least in gcc-4.5) ? Is this a compiler dependent terminology ?
I know that it might appear as basic silly question, but I had never thought of it.
A good reference for this sort of thing is the Itanium ABI - see eg http://mentorembedded.github.com/cxx-abi/abi.html#vtable. Despite the name it's a widely used ABI for C++ and it describes a good, working implementation (although obviously other implementations are possible).
You can solve both problems (virtual function calls and virtual inheritance) if you know the dynamic type of an object given just a pointer to it. Every (polymorphic) object in C++ has precisely one dynamic type, which is determined at the moment when it's constructed. E.g. when you write new Foo, that object has the dynamic type Foo even if you store just a void*.
A vtable is a mechanism to store information about the dynamic type of an object in such a way that it can be retrieved via a base pointer. You can store quite some things in a vtable: function pointers, cast offsets, std::type_info objects even.
Related
The above was an interview question.
I understand that as part of the virtual dispatch mechanism, the compiler creates a vTable for each class and inserts an extra pointer (vptr) during compilation. But when exactly does it assign the class' virtual table to this vptr?
How is the vptr initialized at compile time?
Whatever I read over the internet says that the compiler initializes the vptr at compile time, but initialization is a run-time mechanism. Am I wrong?
I don't understand how a compiler would initialize it.
Strictly speaking, this is not covered by the C++ standard. But enough implementations go for this to consider it common wisdom. I'm going to address only single inheritance, since multiple inheritance is way more complicated.
The compiler knows in advance where a type's virtual function table is located (it's the compiler that allocates it). It also knows all of that class type's constructors. So what it has to do is fairly simple, at the beginning of each constructor, add the following (illustrative):
this->_vptr = /*VTable's Address*/;
That's it. This is exceptionally simple, and even works intuitively when overriding. Because a derived class's constructor will just overwrite the pointer value.
And yes, that assignment, naturally, happens at run-time. Even though the table itself may be populated beforehand.
I found below post
C++ polymorphism without pointers
that explains to have polymorphism feature C++ must use pointer or reference types.
I looked into some further resources all of them says the same but the reason .
Is there any technical difficulty to support polymorphism with values or it is possible but C++ have decided to not to provide that ability ?
The problem with treating values polymorphically boils down to the object slicing issue: since derived objects could use more memory than their base class, declaring a value in the automatic storage (i.e. on the stack) leads to allocating memory only for the base, not for the derived object. Therefore, parts of the object that belong to the derived class may be sliced off. That is why C++ designers made a conscious decision to re-route virtual member-functions to the implementations in the base class, which cannot touch the data members of the derived class.
The difficulty comes from the fact that what you call objects are allocated in automatic memory (on the stack) and the size must be known at compile-time.
Size of pointers are known at compile-time regardless of what they point to, and references are implemented as pointers under the hood, so no worries there.
Consider objects though:
BaseObject obj = ObjectFactory::createDerived();
How much memory should be allocated for obj if createDerived() conditionally returns derived objects? To overcome this, the object returned is sliced and "converted* to a BaseObject whose size is known.
This all stems from the "pay for what you use" mentality.
The short answer is because the standard specifies it. But are there any insurmountable technical barriers to allowing it?
C++ data structures have known size. Polymorphism typically requires that the data structures can vary in size. In general, you cannot store a different (larger) type within the storage of a smaller type, so storing a child class with extra variables (or other reasons to be larger) within storage for a parent class is not generally possible.
Now, we can get around this. We can create a buffer larger than what is required to store the parent class, and construct child classes within that buffer: but in this case, exposure to said instance will be via references, and you will carefully wrap the class.
This is similar to the technique known as "small object optimization" used by boost::any, boost::variant and many implementations of std::string, where we store (by value) objects in a buffer within a class and manage their lifetime manually.
There is also an issue where Derived pointers to an instance can have different values than Base pointers to an instance: value instances of objects in C++ are presumed to exist where the storage for the instance starts by most implementations.
So in theory, C++ could allow polymorphic instances if we restricted it to derived classes that could be stored in the same memory footprint, with the same "pointer to" value for both Derived and Base, but this would be an extremely narrow corner case, and could reduce the kinds of optimizations and assumptions compilers could make about value instances of a class in nearly every case! (Right now, the compiler can assume that value instances of a class C have virtual methods that are not overridden elsewhere, as an example) That is a non trivial cost for an extremely marginal benefit.
What more, we are capable of using the C++ language to emulate this corner case using existing language features (placement new, references, and manual destruction) if we really need it, without imposing that above cost.
It is not immediately clear what you mean by "polymorphism with values". In C++ when you have an object of type A, it always behaves as an object of type A. This is perfectly normal and logical thing to expect. I don't see how it can possible behave in any other way. So, it is not clear what "ability" that someone decided "not to provide" you are talking about.
Polymorphism in C++ means one thing: virtual function calls made through an expression with polymorphic type are resolved in accordance with the dynamic type of that expression (as opposed to static type for non-virtual functions). That's all there is to it.
Polymorphism in C++ always works in accordance with the above rule. It works that way through pointers. It works that way through references. It works that way through immediate objects ("values" as you called them). So, it not not correct to say that polymorphism in C++ only works with pointers and references. It works with "values" as well. They all follow the same rule, as stated above.
However, for an immediate object (a "value") its dynamic type is always the same as it static type. So, even though polymorphism works for immediate values, it does not demonstrate anything truly "polymorphic". The behavior of an immediate object with polymorphism is the same as it would be without polymorphism. So, polymorphism of an immediate object is degenerate, trivial polymorphism. It exists only conceptually. This is, again, perfectly logical: an object of type A should behave as an object of type A. How else can it behave?
In order to observe the actual non-degenerate polymorphism, one needs an expression whose static type is different from its dynamic type. Non-trivial polymorphism is observed when an expression of static type A behaves (with regard to virtual function calls) as an object of different type B. For this an expression of static type A must actually refer to an object of type B. This is only possible with pointers or references. The only way to create that difference between static and dynamic type of an expression is through using pointers or references.
In other words, its not correct to say that polymorphism in C++ only works through pointers or references. It is correct to say is that with pointers or references polymorphism becomes observable and non-trivial.
Any class having a virtual function would get an extra hidden pointer which would point to the most derived class.
What is the type of this vptr?
It has no type. It's an implementation detail unspecified by the standard; it is not part of the language.
Note that C++ doesn't say that there has to be a virtual table or a virtual "pointer" at all (though this is the most common implementation of RTTI in C++ toolchains).
Also, your analysis is wrong. In, say, GCC, usually each object gets a vptr that points to the relevant virtual table for that object's type: object has pointer, type has table.
The standard does not guarantee the presence of the virtual table pointer, even though most implementations use it.
As a result, it has no type. It is simply an array of pointers.
It has compiler-dependent type which may be anything as long as the compiler understands it. As the language doesn't say anything about vptr, neither programmers use it in their code, compilers are free to create any arbitrary type for implementing runtime polymorphism. That type doesn't has to be conformant with the C++ language.
I know that, how to implement virtual function call resolution is not part of C++ standrads nor it says anything about vptr or v-table, but let me ask this question here.
I've heard that v-table is a common technique used by compilers to implement virtual function call resolution. My understading about this is that there is only virtual table is needed per class, per process.
What I am wondering is, when is the v-table is created for a class?
Is it When the class of a given type (which needs a v-table) is created in a process space for the first time?
All other subsequently created objects of that type in that process space, refers to the v-table that is already created?
When would this v-table will be deleted?
I am sorry if this is too subjective or discussion type of question, but these questions lingers in my mind for a while and I feel its OK asking it here.
The v-table is statically allocated and is never deleted, nor is it explicitly allocated. The pointers within any given specific object are constants.
The C++ FAQ provides a simplified explanation of the vtable mechanism. You should give it a read, although you will probably have to go through your particular compiler documentation for more details.
The most important ideas from my point of view :
The vtable for a type is static and built at compile time
Each of the type instances contains a pointer to this table
Because this pointer is initialized at construction time, a virtual member function should never be called from the constructor
The vtable is static data so available immediately at load. BTW, it is usually bundled in the compilation unit which contains the definition for the first non-inline virtual function on the class (and that heuristic leads to problem when there is only one virtual function which is inline).
I believe it's all implementation defined, so it's difficultto give a universal answer to this question. I believe the vtable should be a some sort of a static class member.
I'm not talking about a pointer to an instance, I want a pointer to a class itself.
In C++, classes are not "first class objects". The closest you can get is a pointer to its type_info instance.
No. A pointer is the address of something in the memory of the computer at run-time. A class is just a set of instructions to the compiler.
As everyone else have already said, it's not possible to have a pointer to a class.
But if the point is to create a new instance from some class chosen at runtime, you might want to check out the Factory Method (or Abstract Factory) design patterns.
Yes and No. This depends on your context of what you are trying to achieve. If you simply want a pointer to a type then no there is not a way. A type does not live in memory in the sense of a pointer.
There reason I said yes though is some people would consider the virtual table a pointer to a type. It is possible to get this pointer since the virtual table does exist in memory and can be used to invoke virtual methods with a bit of trickery.
Unlike true Object-Based languages, a class is not an object in C++, more is the pity. The closest you can come to "pointer to class" is RTTI:
const std::type_info &info = typeid(object expression);
type_info has name() member finction, and they can be compared to each other.
A "Class" does not exist. The only thing you can point to is the data.
The rest of a "Class" is actually a dispatch table. For each method in the class, the dispatch table has a pointer. That way, the class points to the correct method of your class regardless of what type it's currently cast to. This would be useless to access.
Methods in your class (the things pointed to by the dispatch table) are actually just "Functions" that are passed in your class data pointer. The definition of a method is pretty much that it's a function that takes the classes data as a parameter. In most C-style languages, that data pointer is hidden but referred to as "this".
The methods for your class may be spread all over the codebase. Because of parent classes, you're not likely even find these methods adjacent to each other.
You can't have a (run-time) pointer to a class, but C++ does has a similar compile-time concept: template parameters. Boost has a library dedicated to manipulating them and a traits library for getting information about classes.
Depending upon how you want to think about pointers, you can have a "pointer" to a class, if by pointer you mean some integral value. Boost allows you to register types and assign a unique integer for every type that you register. If the types you are registering are all classes then you can look up at run-time the code necessary to create an object of the type you want, as long as you have the value of the type you want. But in general, classes aren't first class objects in the language and the best you can hope for is to simulate the behavior you want to have.
True, there is no support for reflection/introspection in built in to C++, but there are a number of libraries that will add many of eg java's Class functionality, and allow a programmer to get an object representing a class, create an instance, etc. google c++ reflection.