class ClassA { public: ClassA() {data = 10;} virtual void set() { std::cout << "ClassA is increasing" << std::endl; data++; } int get() { set(); return data; } protected: int data; }; class ClassB : public ClassA { public: void set() { std::cout << "ClassB is decreasing" << std::endl; data--; } };
ClassA
, which has two methods: get()
and set()
. The get()
method is marked as a virtual function; in class ClassB
its implementation changes. The integer data
marked with the protected
keyword so that the class-descendant ClassB
access to it.
int main() { ClassA classA; ClassB classB; std::cout << "ClassA value: " << classA.get() << std::endl; std::cout << "ClassB value: " << classB.get() << std::endl; return 0; }
ClassA is increasing ClassA value: 11 ClassB is decreasing ClassB value: 9
/* */ struct ClassA; /* , . */ typedef struct { void (*ClassA)(struct ClassA*); /* "" */ void (*set)(struct ClassA*); /* set */ int (*get)(struct ClassA*); /* get */ } ClassA_functiontable; typedef struct ClassA { int data; ClassA_functiontable *vtable; /* ClassA */ } ClassA; /* ClassA */ void ClassA_constructor(ClassA *this); void ClassA_set(ClassA *this); int ClassA_get(ClassA *this); /* ClassA */ ClassA_functiontable ClassA_vtable = {ClassA_constructor, ClassA_set, ClassA_get }; /* */ void ClassA_constructor(ClassA *this) { this->vtable = &ClassA_vtable; this->data = 10; } void ClassA_set(ClassA *this) { printf("ClassA is increasing\n"); this->data++; } int ClassA_get(ClassA *this) { this->vtable->set(this); return this->data; }
this
pointer that points to the caller. I called the parameter so as to mimic the use of the this
pointer in C ++ (besides, this is similar to how an object method call actually works in C ++).
ClassA_get()
calls the set()
function via a pointer from the vtable. Now let's look at the implementation of the heir class:
/* */ struct ClassB; /* , , */ typedef struct { void (*ClassB)(struct ClassB*); void (*set)(struct ClassB*); void (*get)(struct ClassA*); } ClassB_functiontable; typedef struct ClassB { ClassA inherited_class; } ClassB; void ClassB_constructor(ClassB *this); void ClassB_set(ClassB *this); int ClassB_get(ClassB *this); ClassB_functiontable ClassB_vtable = {ClassB_constructor, ClassB_set, ClassB_get}; void ClassB_constructor(ClassB *this) { /* */ ClassA_constructor((ClassA*)this); /* */ this->inherited_class.vtable = (ClassA_functiontable*)&ClassB_vtable; } void ClassB_set(ClassB *this) { printf("ClassB decreasing\n"); this->inherited_class.data--; } int ClassB_get(ClassB *this) { this->inherited_class.vtable->set((ClassA*)this); return this->inherited_class.data; }
set()
function from the implementation of the get()
ClassB using vtable, which points to the desired set()
function, and also access the same integer data
via the “inherited” class ClassA.
main()
function looks like:
int main() { ClassA classA; ClassB classB; ClassA_constructor(&classA); ClassB_constructor(&classB); printf("ClassA value: %d\n", classA.vtable->get(&classA)); /* get() - */ printf("ClassB value: %d\n", classB.inherited_class.vtable->get((struct ClassA*)&classB)); }
ClassA is increasing ClassA value: 11 ClassB decreasing ClassB value: 9
Source: https://habr.com/ru/post/138684/