TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.37K subscribers
Post #964 4.12K
​​Наследие Cfront. Наследование
#новичкам

Сорри за тавталогию, но мимо этой темы мы не можем пройти(хотя я бы прошел, если бы не @shumilkinad, спасибо ему)

В раннем С++ уже были классы и наследование, но в С этого не было. Как же можно транслировать наследование классов в С'шный код?

Простая агрегация и никакого мошенничества.

Все классы в С++ - это простые С-структуры с отдельным набором функций, принимающих cv-специфицированный указатель на инстанс структуры(это мы выяснили в прошлом посте). Наследники же в начале объекта хранят все поля базового класса. Так давайте просто первым полем наследника сделаем инстанс базовой структуры. Таким образом мы обеспечим вложенность объектов с любым количеством наследований.

Вот есть пара родитель-наследник:

class Base {
public:
int x;
Base(int a) : x(a) {}
};

class Derived : public Base {
public:
int y;
int z;
Derived(int a, int b) : Base(a), y(b) {
z = x + y;
}
};


Примерно в такой код они транслировались:

struct Base {
int x;
};

struct Derived {
struct Base _base; // embedded base object
int y;
int z;
};

void Base_constructor(struct Base* this, int a) {
this->x = a;

// Constructor body (if presented)
}

void Derived_constructor(struct Derived* this, int a, int b) {
// Init base object
Base_constructor(&this->_base, a);

// Init fields of derived object
this->y = b;

// Constructor body
this->z = this->_base.x + this->y;
}


Первым полем структуры Derived - структура Base.

Конструкторы же - это отдельные функции. Но в С++ очень важен порядок вызовов конструкторов и деструкторов.

Поэтому конструктор самого базового класса только инициализирует свои поля и дальше выполняет инструкции из тела конструктора. При создании же наследников в начале вызывается конструктор базового класса и лишь потом инициализация полей и выполнение тела.

Разрушение же объекта выполняется в обратном порядке. Трусы снимаются только после штанов, раньше не получится.

class Base {
public:
~Base() {
// Destructor Base body
}
};

class Derived : public Base {
public:
~Derived() {
// Destructor Derived body
}
}


Превращается в:

struct Base {
};

struct Derived {
struct Base _base;

};

void Base_destructor(struct Base* this) {
// Destructor Base body
}

void Derived_destructor(struct Derived* this) {
// Destructors execute in reverse order

// Destructor Derived body

Base_destructor(&this->_base);
}


Новичкам особенно будет полезно понимать, как простой код С++ может быть написан на С, чтобы досканально понимать все абстракции языка и какие действия скрыты от наших глаз.

Have a legacy. Stay cool.

#cppcore #goodoldc #compiler
  • 👍 33
  • ❤ 14
  • 🔥 12
More from @grokaemcpp
  1. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  2. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  3. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  4. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  5. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  6. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →