I am trying to simulate the vptr/vtable concept. I have 3 questions regarding the following:
1. I have not defined any constructor for the class FOO , which should be fine as can be seen inside main(Foo *ptr= new FOO is OK ).
But when i create the object on heap for the same inside FooVtable::bar() , it complains about no appropriate default constructor found. Why?
2. I see that vptr points to some address(even though there is no new FooVTable done for vptr,i guess ctor by default does it. is it expected?), FooVtable::bar is getting called but cout doesnt print the statement. Why?
3. Inside callsomeFun(), i am calling foo->vptr->bar . What i am trying to achieve here is that vptr->bar part of foo->vptr->bar should actually call a pointer to member function Foo::bar() , which i guess isnt directly possible, hence i declared void bar(Foo* foo) inside which i am thinking to call the Foo:bar through ptr. Am i approaching it right, or is there a better way to approach this?
class Foo;
struct FooVtable {
void bar(Foo* foo)
{
//Foo *ptr = new Foo; //Why does this throw error as No Default constructor?
cout<"FooVTable : bar"; //Doesnt get printed even though gets called
}
};
struct Foo {
FooVtable* vptr;
void bar(Foo *foo)
{
cout<<"Foo : bar";
}
};
int callSomeFun(Foo* foo) {
foo->vptr->bar(foo);
return 0;
}
int main()
{
Foo *ptr=new Foo;
callSomeFun(ptr);
return 0;
}
when i create the object on heap for the same inside FooVtable::bar() , it complains about no appropriate default constructor found. Why?
That's a poor error message for a situation where you're trying to use a class before it has been fully declared. On a different compiler the message could be more like "error: invalid use of incomplete type 'class Foo'".
One way to solve it would be to put the full struct Foo stuff above FooVtable and then use a forward declaration of FooVtable instead of Foo.
I see that vptr points to some address(even though there is no new FooVTable done for vptr,i guess ctor by default does it. is it expected?), FooVtable::bar is getting called but cout doesnt print the statement. Why?
That vptr is uninitialized. Primitive types like pointers aren't initialized to any kind of default value by just a new. So whatever is in there is garbage. That much is expected.
Whatever happens after you call a function via a pointer with a garbage value is Undefined Behavior. So just about anything could happen and there wouldn't be a guaranteed explanation.
However in this case there's also another problem: You've made a typo. cout<"FooVTable : bar"; has a single < and thus would do a strange and useless comparison instead of outputting anything.
foo->vptr->bar should actually call a pointer to member function Foo::bar() , which i guess isnt directly possible
Pointers to member functions are possible. You could potentially use one in the situation you've created so far. However once you start bringing inheritance into the scenario (which is where virtual functions are finally useful), it could get interesting to try to make this work out between the different types. (I use member function pointers so rarely that I can't say offhand.)
Am i approaching it right, or is there a better way to approach this?
It really depends on how much of a real implementation you're trying to "simulate" and what you're hoping to achieve by it.
Related
I am trying to make a generic class that can represent any object in its most base form, bits. To do this I created a Union of an array of chars (essentially bytes) and the object that the characters make up. Unfortunately when building, I get a strange warning and error for my union.
Warning: "The destructor was implicitly defined as deleted."
Error: "Attempting to reference a deleted function."
(both occur on the line following the definition of my union)
I know that you can create custom destructors for structs, classes and unions, but there is not a need to if you are not freeing up dynamic memory, correct? Yet somehow a destructor I never defined is being automatically called and the compiler deleted it implicitly. Hence the error.
The next thing I attempted was defining a destructor within my union; it did nothing because I never asked the os for additional memory. It was once again deleted. I needed to figure out why the compiler was deleting my function and then causing an error when trying to call it after it deleted it.
I attempted looking for this error in the Microsoft visual studio list, and what it came up with was that not making the constructor public would cause this error. Additionally, looking online here I found that oftentimes the copy constructor is what causes an error because it was never defined. So i tested it by creating a class of my own and using the copy constructor = on it. It worked just fine, but gave me the same error when attempting to use it with my typeAsChar class. Interestingly enough, this error is not called when I use my class with the C default structs, int, double, etc.
Here is the code that causes the issue.
template <class type>
union typeAsChar
{
type obj;
char arr[sizeof(type)];
};
template <class type>
class wontWork
{
public:
wontWork() {/* Do nothing, no data entered */}
wontWork(const type& obj) { foo.obj = obj; }
~wontWork() {/* When this goes out of scope, the default
destructor of the member 'type' should be called */}
typeAsChar<type> foo;
};
int main()
{
double testNum = 12345;
std::string testStr = "Hello World\n";
wontWork<std::string> test1(testStr); // has error
std::cout << test1.foo.obj;
wontWork<double> test2(testNum); // No error
std::cout << test2.foo.obj;
return 0;
}
Oddly enough, this compiles and runs perfectly with wontWork<std::string> commented out, but fails when my class is made with an object of anything other than the standard c structs (int, double, etc). Any clarification on the matter would be much appreciated.
Here is the answer by #Miles Budnek that worked perfectly. Thanks a lot for your info, I never knew that was a functionality in c++.
"reinterpret_cast(&object) is a well-defined way to access the bytes that make up an object (even if it's not very useful for something like std::string). Type-punning via union is not well-defined. – Miles Budnek"
I came across articles where in they explain about vptr and vtable.
I know that the first pointer in an object in case of a class with virtual functions stored, is a vptr to vtable and vtable's array entries are pointers to the function in the same sequence as they occur in class ( which I have verified with my test program).
But I am trying to understand what syntax must compiler put in order to call the appropriate function.
Example:
class Base
{
virtual void func1()
{
cout << "Called me" << endl;
}
};
int main()
{
Base obj;
Base *ptr;
ptr=&obj;
// void* is not needed. func1 can be accessed directly with obj or ptr using vptr/vtable
void* ptrVoid=ptr;
// I can call the first virtual function in the following way:
void (*firstfunc)()=(void (*)(void))(*(int*)*(int*)ptrVoid);
firstfunc();
}
Questions:
1. But what I am really trying to understand is how compiler replaces the call to ptr->func1() with vptr?
If I were to simulate the call then what should I do? should I overload the -> operator. But even that would not help as I would not know what really the name func1 is. Even if they say that compiler accesses the vtable through vptr, still how does it know that the entry of func1 is the first array adn entry of func2 is the second element in the array? There must be some mapping for the names of function to the elements of array.
2. How can I simulate it. Can you provide the actual syntax that compiler uses to call function func1(how does it replace ptr->func1())?
Don't think of a vtable as an array. It's only an array if you strip it of everything C++ knows about it other than the size of its members. Instead, think of it as a second struct whose members are all pointers to functions.
Suppose I have a class like this:
struct Foo {
virtual void bar();
virtual int baz(int qux);
int quz;
}
int callSomeFun(Foo* foo) {
foo->bar();
return foo->baz(2);
}
Breaking it down 1 step:
class Foo;
// adding Foo* parameter to simulate the this pointer, which
// in the above would be a pointer to foo.
struct FooVtable {
void (*bar)(Foo* foo);
int (*baz)(Foo* foo, int qux);
}
struct Foo {
FooVtable* vptr;
int quz;
}
int callSomeFun(Foo* foo) {
foo->vptr->bar(foo);
return foo->vptr->baz(foo, 2);
}
I hope that's what you're looking for.
The backgroud:
After compilation (without debug info) binaries of C/C++ have no names, and names aren't required to runtime work, its only machine code
You can think about vptr like clasic C function pointer, in sense that type, argument list etc is known.
It isn't important on which positions are placed func1, func2 etc, only required is order was always the same (so all parts of multi file C++ must be compiled in the same way, compiler settings etc). Lets imagine, position is in declaration order, FIRST parent class, then newly declared in override BUT reimplemented virtuals are at lower positions, like from parent.
Its only image. Implementation must correctly fire overrides classApionter->methodReimplementedInB()
Usually C++ compiler has/had (my knowledge is from years 16/32b migration) 2-4 option to optimalize vtables against speed/size etc. Classic C sizeof() was quite well to understand (size of data plus ev. alignment), in C++ sizeof is bigger, but can guarantee if it is 2,4,8 bytes.
4 Few conversion tool can convert "object" files i.e. from MS format to Borland etc, but usually/only classic C was possible/safe, because of unknown machine code implementations of vtable.
Hard to touch vtable from high level code, fire analysers for intermediate files (.obj, . etc)
EDIT: story about runtime is different than about compilation. My answer is about compiled code & runtime
EDIT2: quasi assembler code (from my head)
load ax, 2
call vt[ax]
vt:
0x123456
0x126785 // virlual parent func1()
derrived:
vt:
0x123456
0x126999 // overriden finc1()
0x456788 // new method
EDIT3: BTW I can't totally agree that C++ has always better speed JVM/.NET because "these are interpreted". C++ has part of "intepretation", and interpreted part is groving: real component/GUI frameworks have interpreted connections between too (map for example). Out of our discussion: what memory model is better, with C++ delete or GC?
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Calling class method through NULL class pointer
I was asked this question in the interview can someone answer it?
#include<string>
#include<iostream>
#include <stdio.h>
using namespace std;
class A
{
int k;
public:
void f1()
{
int i;
printf("1");
}
void f2()
{
k = 3;
printf("3");
}
};
class B
{
int i;
public:
virtual void f1()
{
printf("2");
scanf("%d",&i);
}
};
int main()
{
A* a = NULL;
B* b = NULL;
a->f1(); // works why?(non polymorphic)
b->f1(); // fails why?(polymorphic)
a->f2(); //fails why?
}
The last 2 cases are of polymorphic classes. The first case is a normal class .i understand that if i access i in f1 of A it will again give a runtime exception . but i am not getting why that happens
I agree with the other posts that this is undefined behavior, meaning anything can happen when executing the program, including "doing the right thing".
Now, let's look at how the calls are implemented:
a->f1() is a normal method call (non virtual). Most compilers will compile this in a similar way as the following code:
class A { int i; }
void f1(A* a) { int i; printf("1"); }
Meaning the this pointer is actually handled like a parameter to the function (in practice there are frequently some optimizations about how the this pointer is handled, but that is irrelevant here). Now, since f1 doesn't use the this pointer, the fact that it is null doesnt cause a crash.
a->f2() will actually crash because it uses the this pointer: it updates this->k.
The call to b->f1() is a virtual function call, and this is typically implemented using a virtual table lookup as b->vtable[0](). Since b is null, the dereference to read the virtual table crashes.
a->f1();
b->f1();
a->f2();
In all the three cases you are deferefencing a pointer that points to NULL, i.e. it does not point to an object. This constitutes undefined behaviour. They may work by pure chance, but you cannot rely on that. It also doesn't makes much sense to try to figure out why one version could possibly work. Undefined behaviour means anything can happen.
Technically this is all undefined behaviour. So without more background (compiler, used settings) this would be the correct answer.
I don't believe this is what they expected to hear though.
Given that usually a member function call is internally translated in this manner (simplified on purpose):
class A {
void foo(int x) {} // compiler creates function void A_foo(A* this, int x) {}
};
A a;
a.foo(5); // compiler calls A_foo(&a, 5);
BUT the situation is different for virtual functions. I will not explain the principle of virtual dispatch here, but to simplify - the function that gets called in the end is dependent on the dynamic type of the object. If the object doesn't exist, the program can't know what function to call.
As to why your a->f2() fails. Imagine the function A_f2(A* this). Inside you access A's member k. This would in my simplified compiler get translated to this->k = 3. But in the actual call this is a null pointer.
In a way neither of the three cases "works". But in another way, all of the three cases "work".
They all have undefined behaviour, because they all perform indirection through a null pointer.
i understand that if i access i in f1 of A it will again give a runtime exception
Maybe, maybe not. Undefined behaviour is undefined, so anything can happen.
All three examples result in undefined behavior, so this is very implementation specific and not guaranteed to have the same behavior on all compilers.
A common way of implementing virtual functions is to add a pointer to a table of function pointers at the beginning of a class. Whenever a virtual function is called, the program follows this pointer and looks in the table to determine which function to call. Since, in the example of a null-pointer, it is looking at an invalid address for this pointer, this causes a runtime error.
When calling a non-virtual function, the compiler already knows exactly what function to call, so it can directly insert a call to this function; accessing the object is not necessary to determine which function to call. So, if the function itself does not access the object, the function call will never result in an access through the null-pointer, so it won't result in a runtime error.
I was working on a project and, while playing around with the code, I came across the following peculiar occurrence.
I have two classes. The first holds three floats in an array representing Cartesian coordinates and defines a method to get those points;
class foo
{
protected:
float m_Coordinates[3];
public:
foo(float coordinates[3]);
void GetPoints(int resultArray[]);
};
foo::foo(int coordinates[3])
{
std::copy(coordinates, coordinates+3, m_Coordinates);
}
void foo::GetPoints(float resultArray[])
{
std::copy(m_Coordinates, m_Coordinates+3, resultArray);
}
The second class also stores an array of floats, but its constructor uses foo as a wrapper class to pass the values:
class bar
{
protected:
float m_MoreCoordinates[3];
public:
bar(foo f);
};
bar::bar(foo f)
{
f.GetPoints(m_MoreCoordinates);
//m_MoreCoordinates is passed by reference, so the values in
//m_MoreCoordinates are equal to the values in f.m_Coordinates
//after this line executes
}
Please ignore the fact that the approach I've taken to this code is simply horrible. It started out as an experiment in using arrays. Passing them as arguments, getting them as return types etc.
OK. Here's where I noticed something strange. If I declare an array of floats and pass them as an argument to bar's constructor, the compiler will generate an instance of class foo and pass that to bar for me. See example code below:
int main(int argv, char** argc)
{
float coordinates[] = {1.0f, 2.1f, 3.0f};
//Here the compiler creates an instance of class foo and passes
//coordinates as the argument to the constructor. It then passes
//the resulting class to bar's constructor.
bar* b = new bar(coordinates);
//Effectively, the compiler turns the previous line into
//bar* b = new bar(foo(coordinates));
return 0;
}
When I saw this, I thought it was a pretty neat feature of the code and was wondering how and why it happened. Is it safe to do this? I don't understand how it works, and so I don't want to depend on it. If someone could explain how this works, I'd really appreciate it.
Edit:
Thanks to Mankarse for pointing out how the conversion would be performed in the main. Initially, I had:
//Effectively, the compiler turns the previous line into
//bar* b = new bar(*(new foo(coordinates)));
As you guessed, compiler is implicitly creating a foo object and passing it to bar. Generally, this is considered a bit dangerous as the foo gets constructed without knowledge, to avoid this you can declare foos constructor as explicit. In that case compiler will not implicitly create foo from array of floats and you will get an compiler error.
When you think about it, you use this all of the time. Consider the following:
void foo(std::string argument);
Then, suppose you invoke this function using a string literal:
foo("argument");
this is the same as:
std::string argument("argument");
foo(argument);
It's a pretty useful feature.
I have a class set up like this:
class Foo {
Foo();
private:
Bar m_bar;
}
That is the class definition in it's own header file, and now in the source file to go with it I have the constructor and I tried doing this:
Foo::Foo() {
m_bar("parameters for the Bar constructor");
}
However this doesn't work and gives me an error. I can make m_bar a pointer and then in Foo's constructor do this:
m_bar = new Bar("parameters here");
However that makes m_bar a pointer and I don't want that.
I'm not the best with C++ classes and pointers, so could something either explain a way for me to have m_bar defined in the Foo class but constructor somewhere else or if it is better to make m_bar a pointer in this situation explain why? While I would rather not make it a pointer(because I don't understand pointers extremely well), if that is the best way to do it then I would rather do it that way, but I'd still like someone to explain why that is the best way to do it(if it is).
Yes, using the initializer list syntax:
Foo::Foo() :
m_bar("parameters for the Bar constructor")
{
}
You need to use initialization lists:
Foo::Foo() :
m_bar("and you ought to check out a good C++ book :)")
{
// Book list: http://tinyurl.com/so-cxxbooks
}
If I'm understanding you right, you can use the constructor initialization list to do so.