Bootstrapping Classes
Did you know that in the early days of C++, it was just a thin veneer over C? Classes were just syntactic sugar that were translated into C code. Suppose you had this Hero
class:
class Hero {
public:
Hero(char* name, int hit_points) {
this->name = strdup(name);
this->hit_points = hit_points;
}
void cure(int boost) {
hit_points += boost;
}
private:
char* name;
int hit_points;
}
class Hero { public: Hero(char* name, int hit_points) { this->name = strdup(name); this->hit_points = hit_points; } void cure(int boost) { hit_points += boost; } private: char* name; int hit_points; }
Somehow this code had to get translated into C, where classes weren't a thing. But C does have structs, so Hero
would get turned into one like this:
struct Hero {
char* name;
int hit_points;
}
struct Hero { char* name; int hit_points; }
What about the methods of Hero
? They'd get turned into regular C functions:
void cure(struct Hero *hero, int boost) {
hero->hit_points += boost;
}
void cure(struct Hero *hero, int boost) { hero->hit_points += boost; }
Notice how the receiver becomes the first formal parameter. But it wasn't called hero
. It was called this
:
void cure(struct Hero *this, int boost) {
this->hit_points += boost;
}
void cure(struct Hero *this, int boost) { this->hit_points += boost; }
What happened when we instantiated an object, like this?
int main() {
Hero *frank = new Hero("Frank", 260);
// ...
}
int main() { Hero *frank = new Hero("Frank", 260); // ... }
It turned into code like this:
void initialize_hero(struct Hero *this, char *name, int hit_points) {
this->name = strdup(name);
this->hit_points = hit_points;
}
int main() {
struct Hero *frank = (struct Hero *) malloc(sizeof(struct Hero));
initialize_hero(frank, "Frank", 260);
// ...
}
void initialize_hero(struct Hero *this, char *name, int hit_points) { this->name = strdup(name); this->hit_points = hit_points; } int main() { struct Hero *frank = (struct Hero *) malloc(sizeof(struct Hero)); initialize_hero(frank, "Frank", 260); // ... }
As C++ grew and got its own compiler, it stopped translating classes into C and went directly into machine code. Yet this translation to C still hints at how objects are treated internally.