C++ class object memory map - c++

When we create an object of a class what does it memory map look like. I am more interested in how the object calls the non virtual member functions. Does the compiler create a table like vtable which is shared between all objects?
class A
{
public:
void f0() {}
int int_in_b1;
};
A * a = new A;
What will be the memory map of a?

You can imagine this code:
struct A {
void f() {}
int int_in_b1;
};
int main() {
A a;
a.f();
return 0;
}
Being transformed into something like:
struct A {
int int_in_b1;
};
void A__f(A* const this) {}
int main() {
A a;
A__f(&a);
return 0;
}
Calling f is straight-forward because it's non-virtual. (And sometimes for virtual calls, the virtual dispatch can be avoided if the dynamic type of the object is known, as it is here.)
A longer example that will either give you an idea about how virtual functions work or terribly confuse you:
struct B {
virtual void foo() { puts(__func__); }
};
struct D : B {
virtual void foo() { puts(__func__); }
};
int main() {
B* a[] = { new B(), new D() };
a[0]->foo();
a[1]->foo();
return 0;
}
Becomes something like:
void B_foo(void) { puts(__func__); }
void D_foo(void) { puts(__func__); }
struct B_VT {
void (*foo)(void);
}
B_vtable = { B_foo },
D_vtable = { D_foo };
typedef struct B {
struct B_VT* vt;
} B;
B* new_B(void) {
B* p = malloc(sizeof(B));
p->vt = &B_vtable;
return p;
}
typedef struct D {
struct B_VT* vt;
} D;
D* new_D(void) {
D* p = malloc(sizeof(D));
p->vt = &D_vtable;
return p;
}
int main() {
B* a[] = {new_B(), new_D()};
a[0]->vt->foo();
a[1]->vt->foo();
return 0;
}
Each object only has one vtable pointer, and you can add many virtual methods to the class without affecting object size. (The vtable grows, but this is stored once per class and is not significant size overhead.) Note that I've simplified many details in this example, but it does work: destructors are not addressed (which should additionally be virtual here), it leaks memory, and the __func__ values will be slightly different (they're generated by the compiler for the current function's name), among others.

Recognize that the C++ language doesn't specify or mandate everything about memory layout for objects. That said, most compilers do it pretty much the same.
In your example, objects of type A require only enough memory to hold an int. Since it has no virtual functions, it needs no vtable. If the f0 member had been declared virtual, then objects of type A would typically start with a pointer to the class A vtable (shared by all objects of type A) followed by the int member.
In turn, the vtable has a pointer to each virtual function, defined, inherited or overridden. Calling a virtual function for an object consists of following the pointer to the vtable from the object, then using a fixed offset into the vtable (determined at compile time for each virtual function) to find the address of the function to call.

functions are not stored based on what class they are in.
usually the compiler will just treat any member function just like any other function except adds an argument for the 'this' pointer. which is automatically passed to the function when you called it based on the address of the object it is called on.
all functions, static, member, or even virtual member are stored in memory in the same way, they are all just functions.
when the compiler builds the code it pretty much hard codes where it goes into memory, then the linker goes through your code and replaces the "call the function with this name" command with "call the function at this hard coded address"

class A
{
public:
void f0() {}
void f1(int x) {int_in_b1 = x; }
int int_in_b1;
};
A *a = new A();
is internally implemented (represented) like this: (function name are actually mangled)
struct A
{
int int_in_b1;
};
void Class_A__constructor(struct a*) {} // default constructor
void Class_A__f0(struct a*) {}
void Class_A__f1(struct a*, int x) {a->int_in_b1 = x;}
// new is translated like this: (inline)
void* new() {
void* addr = malloc(sizeof(struc a));
Class_A__constructor(addr);
return addr;
}
It can be verify by doing a command "nm" on the object file (result with mangled named)

Related

Number of vtable that will be created

Here if I leave class B as empty then total how many vtables will be created here ?
#include <bits/stdc++.h>
using namespace std;
class A{
public:
virtual void display(){
cout<<"A Class"<<endl;
}
};
class B: public A{
public:
};
int main()
{
A *ob = new B();
ob->display();//A Class
return 0;
}
I was assuming still 2 vtable will be created one in A and 1 in B but for Class B it will be empty and as per design of c++ if we call display function then if it doesn't find the function in its vtable then it will look for the vtable in parent class and will set the binding of that function with vptr but, I am not sure of that.
Can anybody explain with the exact concept
I tired finding the answer over the internet but, didn't get the desired answer
Practically B needs some run time type information, which is typically stored as part of the "vtable" , that is distinct from A.
This is because:
bool test(A* a) {
return dynamic_cast<B*>(a);
}
has to behave differently if we pass a pointer-to-B or a pointer-to-A.
A "typical" way to implement vtables in C++ looks like this:
using vfunc = void(*)(void*);
template<auto creator>
static auto const* get_vtable() {
static const auto table = creator();
return &table;
}
struct A_vtable {
void const* rtti;
void(*display)(void*);
};
A_vtable create_A_vtable_A() {
return {
"This is class A!",
[](void* self) {
std::cout<<"A Class"<<std::endl;
}
};
}
struct A {
A_vtable const* vtable;
A():vtable(get_vtable<&create_A_vtable_A>()) {}
};
struct B_vtable:A_vtable {
};
B_vtable create_B_vtable_B() {
B_vtable vtable = create_A_vtable_A;
vtable.rtti = "This is class B!";
}
struct B:A {
B() {
vtable = get_vtable<&create_B_vtable_B>();
}
};
with the note that my runtime type information is intentionally a joke.
That RTTI information in a real situation will tell you how what the runtime type is, and how to get a pointer to the most-derived type. Here I just store a void pointer to a string.
But you'll notice I moved the vtable pointer to a different table in the constructor of B. This is basically how compilers do it (the standard gives compilers lots of freedom, so you cannot assume it looks anything at all like the above, it might not even have a vtable).

How does the compiler know which entry in vtable corresponds to a virtual function?

Let's say we have more than one virtual function in the parent class and derived class. There will be a vtable created for these virtual functions in the vtable for both the parent derived class.
How will the compiler know which entry in the vtable correspond to which virtual function?
Example:
class Animal{
public:
void fakeMethod1(){}
virtual void getWeight(){}
void fakeMethod2(){}
virtual void getHeight(){}
virtual void getType(){}
};
class Tiger:public Animal{
public:
void fakeMethod3(){}
virtual void getWeight(){}
void fakeMethod4(){}
virtual void getHeight(){}
virtual void getType(){}
};
main(){
Animal a* = new Tiger();
a->getHeight(); // A will now point to the base address of vtable Tiger
//How will the compiler know which entry in the vtable corresponds to the function getHeight()?
}
I have not found exact explanation in my research -
https://stackoverflow.com/a/99341/437894 =
"This table is used to resolve the function call as it contains the
addresses of all the virtual functions of that class."
How exactly is the table used to resolve the function call?
https://stackoverflow.com/a/203136/437894 =
"So at runtime, the code just uses the object's vptr to locate the
vtbl, and from there the address of the actual overridden function."
I am not able to understand this. Vtable holds the address of the virtual function not the address of actual overridden function.
I'll modify your example a little so it shows more interesting aspects of object orientation.
Suppose we have the following:
#include <iostream>
struct Animal
{
int age;
Animal(int a) : age {a} {}
virtual int setAge(int);
virtual void sayHello() const;
};
int
Animal::setAge(int a)
{
int prev = this->age;
this->age = a;
return prev;
}
void
Animal::sayHello() const
{
std::cout << "Hello, I'm an " << this->age << " year old animal.\n";
}
struct Tiger : Animal
{
int stripes;
Tiger(int a, int s) : Animal {a}, stripes {s} {}
virtual void sayHello() const override;
virtual void doTigerishThing();
};
void
Tiger::sayHello() const
{
std::cout << "Hello, I'm a " << this->age << " year old tiger with "
<< this->stripes << " stripes.\n";
}
void
Tiger::doTigerishThing()
{
this->stripes += 1;
}
int
main()
{
Tiger * tp = new Tiger {7, 42};
Animal * ap = tp;
tp->sayHello(); // call overridden function via derived pointer
tp->doTigerishThing(); // call child function via derived pointer
tp->setAge(8); // call parent function via derived pointer
ap->sayHello(); // call overridden function via base pointer
}
I'm ignoring the good advice that classes with virtual function members should have a virtual destructor for the purpose of this example. I'm going to leak the object anyway.
Let's see how we can translate this example into good old C where there are no member functions, leave alone with virtual ones. All of the following code is C, not C++.
The struct animal is simple:
struct animal
{
const void * vptr;
int age;
};
In addition to the age member, we have added a vptr that will be the pointer to the vtable. I'm using a void pointer for this because we'll have to do ugly casts anyway and using void * reduces the ugliness a little.
Next, we can implement the member functions.
static int
animal_set_age(void * p, int a)
{
struct animal * this = (struct animal *) p;
int prev = this->age;
this->age = a;
return prev;
}
Note the additional 0-th argument: the this pointer that is passed implicitly in C++. Again, I'm using a void * pointer as it will simplify things later on. Note that inside any member function, we always know the type of the this pointer statically so the cast is no problem. (And at the machine level, it doesn't do anything at all anyways.)
The sayHello member is defined likewise except that the this pointer is const qualified this time.
static void
animal_say_hello(const void * p)
{
const struct animal * this = (const struct animal *) p;
printf("Hello, I'm an %d year old animal.\n", this->age);
}
Time for the animal vtable. First we have to give it a type, which is straight-forward.
struct animal_vtable_type
{
int (*setAge)(void *, int);
void (*sayHello)(const void *);
};
Then we create a single instance of the vtable and set it up with the correct member functions. If Animal had have a pure virtual member, the corresponding entry would have a NULL value and were better not dereferenced.
static const struct animal_vtable_type animal_vtable = {
.setAge = animal_set_age,
.sayHello = animal_say_hello,
};
Note that animal_set_age and animal_say_hello were declared static. That's onkay because they will never be referred to by-name but only via the vtable (and the vtable only via the vptr so it can be static too).
We can now implement the constructor for Animal…
void
animal_ctor(void * p, int age)
{
struct animal * this = (struct animal *) p;
this->vptr = &animal_vtable;
this->age = age;
}
…and the corresponding operator new:
void *
animal_new(int age)
{
void * p = malloc(sizeof(struct animal));
if (p != NULL)
animal_ctor(p, age);
return p;
}
About the only thing interesting is the line where the vptr is set in the constructor.
Let's move on to tigers.
Tiger inherits from Animal so it gets a struct tiger sub-object. I'm doing this by placing a struct animal as the first member. It is essential that this is the first member because it means that the first member of that object – the vptr – has the same address as our object. We'll need this later when we'll do some tricky casting.
struct tiger
{
struct animal base;
int stripes;
};
We could also have simply copied the members of struct animal lexically at the beginning of the definition of struct tiger but that might be harder to maintain. A compiler doesn't care about such stylistic issues.
We already know how to implement the member functions for tigers.
void
tiger_say_hello(const void * p)
{
const struct tiger * this = (const struct tiger *) p;
printf("Hello, I'm an %d year old tiger with %d stripes.\n",
this->base.age, this->stripes);
}
void
tiger_do_tigerish_thing(void * p)
{
struct tiger * this = (struct tiger *) p;
this->stripes += 1;
}
Note that we are casting the this pointer to struct tiger this time. If a tiger function is called, the this pointer had better point to a tiger, even if we are called through a base pointer.
Next to the vtable:
struct tiger_vtable_type
{
int (*setAge)(void *, int);
void (*sayHello)(const void *);
void (*doTigerishThing)(void *);
};
Note that the first two members are exactly the same as for animal_vtable_type. This is essential and basically the the direct answer to your question. It would have been more explicit, perhaps, if I had placed a struct animal_vtable_type as the first member. I want to emphasize that the object layout would have been exactly the same except that we couldn't play our nasty casting tricks in this case. Again, these are aspects of the C language, not present at machine level so a compiler is not bothered by this.
Create a vtable instance:
static const struct tiger_vtable_type tiger_vtable = {
.setAge = animal_set_age,
.sayHello = tiger_say_hello,
.doTigerishThing = tiger_do_tigerish_thing,
};
And implement the constructor:
void
tiger_ctor(void * p, int age, int stripes)
{
struct tiger * this = (struct tiger *) p;
animal_ctor(this, age);
this->base.vptr = &tiger_vtable;
this->stripes = stripes;
}
The first thing the tiger constructor does is calling the animal constructor. Remember how the animal constructor sets the vptr to &animal_vtable? This is the reason why calling virtual member functions from a base class constructor ofter surprises people. Only after the base class constructor has run, we re-assign the vptr to the derived type and then do our own initialization.
operator new is just boilerplate.
void *
tiger_new(int age, int stripes)
{
void * p = malloc(sizeof(struct tiger));
if (p != NULL)
tiger_ctor(p, age, stripes);
return p;
}
We're done. But how do we call a virtual member function? For this, I'll define a helper macro.
#define INVOKE_VIRTUAL_ARGS(STYPE, THIS, FUNC, ...) \
(*((const struct STYPE ## _vtable_type * *) (THIS)))->FUNC( THIS, __VA_ARGS__ )
Now, this is ugly. What it does is taking the static type STYPE, a this pointer THIS and the name of the member function FUNC and any additional arguments to pass to the function.
Then, it constructs the type name of the vtable from the static type. (The ## is the preprocessor's token pasting operator. For example, if STYPE is animal, then STYPE ## _vtable_type will expand to animal_vtable_type.)
Next, the THIS pointer is casted to a pointer to a pointer to the just derived vtable type. This works because we've made sure to put the vptr as the first member in every object so it has the same address. This is essential.
Once this is done, we can dereference the pointer (to get the actual vptr) and then ask for its FUNC member and finally call it. (__VA_ARGS__ expands to the additional variadic macro arguments.) Note that we also pass the THIS pointer as the 0-th argument to the member function.
Now, the acatual truth is that I had to define an almost identical macro again for functions that take no arguments because the preprocessor does not allow a variadic macro argument pack to be empty. So shall it be.
#define INVOKE_VIRTUAL(STYPE, THIS, FUNC) \
(*((const struct STYPE ## _vtable_type * *) (THIS)))->FUNC( THIS )
And it works:
#include <stdio.h>
#include <stdlib.h>
/* Insert all the code from above here... */
int
main()
{
struct tiger * tp = tiger_new(7, 42);
struct animal * ap = (struct animal *) tp;
INVOKE_VIRTUAL(tiger, tp, sayHello);
INVOKE_VIRTUAL(tiger, tp, doTigerishThing);
INVOKE_VIRTUAL_ARGS(tiger, tp, setAge, 8);
INVOKE_VIRTUAL(animal, ap, sayHello);
return 0;
}
You might be wondering what happens in the
INVOKE_VIRTUAL_ARGS(tiger, tp, setAge, 8);
call. What we are doing is to invoke the non-overridden setAge member of Animal on a Tiger object referred to via a struct tiger pointer. This pointer is first implicitly casted to a void pointer and as such passed as the this pointer to animal_set_age. That function then casts it to a struct animal pointer. Is this correct? It is, because we were careful to put the struct animal as the very first member in struct tiger so the address of the struct tiger object is the same as the address for the struct animal sub-object. It's the same trick (only one level less) we were playing with the vptr.
It can help to implement something similar yourself.
struct Bob;
struct Bob_vtable {
void(*print)(Bob const*self) = 0;
Bob_vtable(void(*p)(Bob const*)):print(p){}
};
template<class T>
Bob_vtable const* make_bob_vtable(void(*print)(Bob const*)) {
static Bob_vtable const table(+print);
return &table;
}
struct Bob {
Bob_vtable const* vtable;
void print() const {
vtable->print(this);
}
Bob():vtable( make_bob_vtable<Bob>([](Bob const*self){
std::cout << "Bob\n";
})) {}
protected:
Bob(Bob_vtable const* t):vtable(t){}
};
struct Alice:Bob {
int x = 0;
Alice():Bob( make_bob_vtable<Alice>([](Bob const*self){
std::cout << "Alice " << static_cast<Alice const*>(self)->x << '\n';
})) {}
};
live example.
Here we have an explicit vtable stored in Bob. It points to a table of functions. The non-virtual member function print uses it to dynamically dispatch to the correct method.
The constructor of Bob and derived class Alice set the vtable to a different value (created as a static local in this case) with different values in the table.
Which pointer to use is baked into the definition of what Bob::print means -- it knows the offset into the table.
If we add another virtual function in Alice, it just means that the vtable pointer will point to a struct Alice_vtable:Bob_vtable in actuality. Static/reinterpret casting will get us the "real" table out, and we can access the extra function pointers easily.
Things get stranger when we talk about virtual inheritance as well as virtual functions. I am not qualified to describe how that works.

What is early (static) and late (dynamic) binding in C++?

How does early and late binding look like in C++? Can you give example?
I read that function overloading is early binding and virtual functions is late binding. I read that "early (or static) binding refers to compile time binding and late (or dynamic) binding refers to runtime binding".
You read right. The basic example can be given with:
using FuncType = int(*)(int,int); // pointer to a function
// taking 2 ints and returning one.
int add(int a, int b) { return a + b; }
int substract(int a, int b) { return a - b; }
Static binding is when binding is known at compile time:
int main() {
std::cout << add(4, 5) << "\n";
}
leaves no room for a dynamic change of the operation, and thus is statically bound.
int main() {
char op = 0;
std::cin >> op;
FuncType const function = op == '+' ? &add : &substract;
std::cout << function(4, 5) << "\n";
}
whereas here, depending on the input, one gets either 9 or -1. This is dynamically bound.
Furthermore, in object oriented languages, virtual functions can be used to dynamically bind something. A more verbose example could thus be:
struct Function {
virtual ~Function() {}
virtual int doit(int, int) const = 0;
};
struct Add: Function {
virtual int doit(int a, int b) const override { return a + b; }
};
struct Substract: Function {
virtual int doit(int a, int b) const override { return a - b; }
};
int main() {
char op = 0;
std::cin >> op;
std::unique_ptr<Function> func =
op == '+' ? std::unique_ptr<Function>{new Add{}}
: std::unique_ptr<Function>{new Substract{}};
std::cout << func->doit(4, 5) << "\n";
}
which is semantically equivalent to the previous example... but introduces late binding by virtual function which is common in object-oriented programming.
These are true of all object-oriented languages, not just C++.
Static, compile time binding is easy. There's no polymorphism involved. You know the type of the object when you write and compile and run the code. Sometimes a dog is just a dog.
Dynamic, runtime binding is where polymorphism comes from.
If you have a reference that's of parent type at compile type, you can assign a child type to it at runtime. The behavior of the reference will magically change to the appropriate type at runtime. A virtual table lookup will be done to let the runtime figure out what the dynamic type is.
Static binding:
if the function calling is known at compile time then it is known as static binding. in static binding type of object matter accordingly suitable function is called. as shown in the example below obj_a.fun() here obj_a is of class A that's why fun() of class is called.
#include<iostream>
using namespace std;
class A{
public:
void fun()
{cout<<"hello world\n";}
};
class B:public A{
public:
void show()
{cout<<"how are you ?\n";}
};
int main()
{
A obj_a; //creating objects
B obj_b;
obj_a.fun(); //it is known at compile time that it has to call fun()
obj_b.show(); //it is known at compile time that it has to call show()
return 0;
}
dynamic binding:
if the function calling is known at run time then it is known as dynamic binding. we achieve late binding by using virtual keyword.as base pointer can hold address of child pointers also. so in this content of the pointer matter.whether pointer is holding the address of base class or child class
#include<iostream>
using namespace std;
class car{
public:
virtual void speed()
{
cout<<"ordinary car: Maximum speed limit is 200kmph\n";
}
};
class sports_car:public car{
void speed()
{
cout<<"Sports car: Maximum speed is 300kmph\n";
}
};
int main()
{
car *ptr , car_obj; // creating object and pointer to car
sports_car sport_car_obj; //creating object of sport_car
ptr = &sport_car_obj; // assigining address of sport_car to pointer
//object of car
ptr->speed(); // it will call function of sports_car
return 0;
}
if we remove virtual keyword from car class then it will call function of car class. but now it is calling speed function of sport_car class.
this is dynamic binding as during function calling the content of the pointer matter not the type of pointer. as ptr is of type car but holding the address of sport_car that's why sport_car speed() is called.

The use case of 'this' pointer in C++

I understand the meaning of 'this', but I can't see the use case of it.
For the following example, I should teach the compiler if the parameter is the same as member variable, and I need this pointer.
#include <iostream>
using namespace std;
class AAA {
int x;
public:
int hello(int x) { this->x = x;}
int hello2(int y) {x = y;} // same as this->x = y
int getx() {return x;}
};
int main()
{
AAA a;
a.hello(10); // x <- 10
cout << a.getx();
a.hello2(20); // x <- 20
cout << a.getx();
}
What would be the use case for 'this' pointer other than this (contrived) example?
Added
Thanks for all the answers. Even though I make orangeoctopus' answer as accepted one, it's just because he got the most vote. I must say that all the answers are pretty useful, and give me better understanding.
Sometimes you want to return yourself from an operator, such as operator=
MyClass& operator=(const MyClass &rhs) {
// assign rhs into myself
return *this;
}
The 'this' pointer is useful if a method of the class needs to pass the instance (this) to another function.
It's useful if you need to pass a pointer to the current object to another function, or return it. The latter is used to allow stringing functions together:
Obj* Obj::addProperty(std::string str) {
// do stuff
return this;
}
obj->addProperty("foo")->addProperty("bar")->addProperty("baz");
In C++ it is not used very often. However, a very common use is for example in Qt, where you create a widget which has the current object as parent. For example, a window creates a button as its child:
QButton *button = new QButton(this);
When passing a reference to an object within one of its methods. For instance:
struct Event
{
EventProducer* source;
};
class SomeContrivedClass : public EventProducer
{
public:
void CreateEvent()
{
Event event;
event.source = this;
EventManager.ProcessEvent(event);
}
};
Besides obtaining a pointer to your own object to pass (or return) to other functions, and resolving that an identifier is a member even if it is hidden by a local variable, there is an really contrived usage to this in template programming. That use is converting a non-dependent name into a dependent name. Templates are verified in two passes, first before actual type substitution and then again after the type substitution.
If you declare a template class that derives from one of its type parameters you need to qualify access to the base class members so that the compiler bypasses the verification in the first pass and leaves the check for the second pass:
template <typename T>
struct test : T {
void f() {
// print(); // 1st pass Error, print is undefined
this->print(); // 1st pass Ok, print is dependent on T
}
};
struct printer {
void print() { std::cout << "print"; }
};
struct painter {
void paint() { std::cout << "paint"; }
};
int main() {
test<printer> t; // Instantiation, 2nd pass verifies that test<printer>::print is callable
t.f();
//test<painter> ouch; // 2nd pass error, test<painter>::print does not exist
}
The important bit is that since test inherits from T all references to this are dependent on the template argument T and as such the compiler assumes that it is correct and leaves the actual verification to the second stage. There are other solutions, like actually qualifying with the type that implements the method, as in:
template <typename T>
struct test2 : T {
void f() {
T::print(); // 1st pass Ok, print is dependent on T
}
};
But this can have the unwanted side effect that the compiler will statically dispatch the call to printer::print regardless of whether printer is a virtual method or not. So with printer::print being declared virtual, if a class derives from test<print> and implements print then that final overrider will be called, while if the same class derived from test2<print> the code would call printer::print.
// assumes printer::print is virtual
struct most_derived1 : test<printer> {
void print() { std::cout << "most derived"; }
};
struct most_derived2 : test2<printer> {
void print() { std::cout << "most derived"; }
};
int main() {
most_derived1 d1;
d1.f(); // "most derived"
most_derived2 d2;
d2.f(); // "print"
}
You can delete a dynamically created object by calling delete this from one of its member functions.
The this pointer is the pointer to the object itself. Consider for example the following method:
class AAA {
int x;
public:
int hello(int x) { some_method(this, x);}
};
void somefunc(AAA* a_p)
{
......
}
class AAA {
int x;
public:
int hello(int x) { this->x = x;}
int hello2(int y) {x = y;} // same as this.x = y
int getx() {return x;}
void DoSomething() { somefunc(this); }
};
this is implicit whenever you use a member function or variable without specifying it. Other than that, there are many, many situations in which you'll want to pass the current object to another function, or as a return value.
So, yeah, it's quite useful.
Sometimes you need to refer to "this" object itself, and sometimes you may need to disambiguate in cases where a local variable or a function parameter shadows a class member:
class Foo {
int i;
Foo* f() {
return this; // return the 'this' pointer
}
void g(){
j(this); // pass the 'this' pointer to some function j
}
void h(int i) {
this->i = i; // need to distinguish between class member 'i' and function parameter 'i'
}
};
The two first cases (f() and g() are the most meaningful cases. The third one could be avoided just by renaming the class member variable, but there's no way around using this in the first two cases.
Another possible use case of this:
#include <iostream>
using namespace std;
class A
{
public:
void foo()
{
cout << "foo() of A\n";
}
};
class B : A
{
public:
void foo()
{
((A *)this)->foo(); // Same as A::foo();
cout << "foo() of B\n";
}
};
int main()
{
B b;
b.foo();
return 0;
}
g++ this.cpp -o this
./this
foo() of A
foo() of B
One more use of this is to prevent crashes if a method is called on a method is called on a NULL pointer (similar to the NULL object pattern):
class Foo
{
public:
void Fn()
{
if (!this)
return;
...
}
};
...
void UseFoo(Foo* something)
{
something->Fn(); // will not crash if Foo == NULL
}
If this is useful or not depends on the context, but I've seen it occasionally and used it myself, too.
self-assignment protection

C++ ...when all the arguments have default values

I guess that this is a very absurd/basic question, but still:
class m
{
public:
void f(int ***);
/***/
}
void m::f(int ***a = NULL)
{
/***/
}
The call to f (as well as any function which has default values for all the arguments) doesn't accept 0 arguments. Why? How should I format the declaration then?
That works fine if the function definition is in the header file. The rule is that whoever is calling the function has to 'see' the default value.
So, I'm guessing you have the function definition in a separate source file. Assuming that's the case, just put the default in the function declaration (in the class):
class m
{
public:
void f(int *** = 0);
/***/
};
You'll also need to remove the default value from the function definition as you can only define the default in a single place (even if the value itself is the same).
This will work:
class m
{
public:
void f(int ***a = NULL);
};
void m::f(int ***a)
{
}
Default values in C++ are syntactic sugar; the compiler essentially inserts the argument for you at the callsite. This means that the compiler needs to know what the default value is, so it must be supplied by the function declaration.
This also means that if you have inheritance and virtual methods, the default values used are the ones from the static type (i.e., what type the compiler thinks the object is), not from the runtime type. For example:
class Base
{
public:
virtual ~Base() { }
virtual std::string foo(std::string s = "b") { return "Base:" + s; }
};
class Derived
: public Base
{
public:
virtual std::string foo(std::string s = "d") { return "Derived:" + s; }
};
int main(void)
{
Derived d;
Base& b = d;
std::cout << b.foo() << std::endl;
return 0;
}
will print Derived:b, not Derived:d.