Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

OO-like C Programming: Struct Inheritance and Virtual Function

In this short presentation struct inheritance and virtual member function in pure C are demonstrated. With these fundamental techniques, more advanced design patterns are unlocked.

  • Identifiez-vous pour voir les commentaires

OO-like C Programming: Struct Inheritance and Virtual Function

  1. 1. OO-Like C: Struct Inheritance and Virtual Functions Yosen Chen
  2. 2. Outline ● Implement the following Object-Oriented techniques in Pure C: ○ Struct “inheritance” ○ Member functions using member variables/functions ○ “Virtual” functions ● PS: ○ I’m not going to condemn non-OO like C, but provide more programming techniques in C. We may base on the task situations to consider its fitness.
  3. 3. Struct Inheritance
  4. 4. Class Inheritance in C++ and C (1/2) This is how we do class inheritance in C++: // A and B are derived from Base class Base { public: int type; int op_Base(int i); }; class A : public Base { public: int* dataA; int op_A(int i); }; class B : public Base { public: int* dataB; int op_B(int i); }; This is how we do struct “inheritance” in C: struct Base { int type; int (*op_Base) (struct Base* _this, int i); }; struct A { struct Base _base; // inherit from Base int* dataA; int (*op_A) (struct A* _this, int i); }; struct B { struct Base _base; //inherit from Base int* dataB; int (*op_B) (struct B* _this, int i); }; PS: I would tell you why we need _this later
  5. 5. Class Inheritance in C++ and C (1/2) In C++, for derived class A, we can access members of both Base and A: Given we have: A a; Then we can use: a.dataA a.op_A(5); a.type a.op_Base(5); We can do the same thing in C as we do in C++: Given we have: struct A a; Then we can use: a.dataA a.op_A(&a, 5); and a._base.type a._base.op_Base(&a._base, 5); or, more elegantly struct Base* pBase = (struct Base*)&a; pBase->type pBase->op_Base(pBase, 5); PS: in this way, struct A users can access Base members as they are struct Base users.
  6. 6. Memory Allocation of Struct “Inheritance” AddrOffset 0~3: type AddrOffset 4~7: op_Base AddrOffset 8~11: dataA AddrOffset 12~15: op_A ... start address of a (i.e., &a) if we declare struct A a; The memory allocation of a is like: a._base a Remark: start address of a == &a == &a._base == &a._base.type a._base.type == ((struct Base*)&a)->type //this concept can be used in virtual
  7. 7. Member Functions Using Other Members
  8. 8. Member Function Using Other Class Members (C++ vs. C) In C++, member functions can access other class members (functions, variables): For example, we can define function op_A as below: int A::op_A(int i) { return op_Base(i) + type + dataA[i]; } We can do the same thing in C as we do in C++: (using _this) int A_op_A(struct A* _this, int i) { return _this->_base.op_Base(&_this->_base, i) + _this->_base.type + _this->dataA[i]; } For struct construction, we have: void A_ctor(struct A* _this) { Base_ctor(&_this->_base); // call Base ctor _this->op_A = A_op_A; ... } For A’s user, we call: a.op_A(&a, 5);
  9. 9. Virtual Function
  10. 10. Virtual Functions in C++ Why we need virtual? ● What is virtual function? ○ By Wikipedia’s definition: In object-oriented programming, a virtual function or virtual method is a function or method whose behavior can be overridden within an inheriting class by a function with the same signature. This concept is an important part of the polymorphism portion of object-oriented programming (OOP) ● Advantages: (better software architecture design) 1. base class users can use derived classes without modifying their code. 2. we can localize the knowledge of which derived class is being used.
  11. 11. Virtual Functions in C++ In C++, virtual function goes like this: class Interface { ... virtual bool execute(); } class ImpA : public Interface { … virtual bool execute(); } class ImpADerived : public ImpA { ... virtual bool execute(); } For general class Interface users: void func(Interface* pInterf) { pInterf->execute(); } ImpADerived a; func(&a); PS: actually, ImpADerived::execute() is called, instead of Interface::execute() PS: Inside func(), it doesn’t need to know which version of execute() is being used. Class Userhold Actually,ituses...
  12. 12. “Virtual” Functions in Pure C (1/2) In C, virtual functions can be achieved via pointer manipulation: struct Interface { ... BOOL (*execute) (struct Interface* _this); } struct ImpA { struct Interface _base; //derived from Interface ... } struct ImpADerived { struct ImpA _base; //derived from ImpA … } in ImpADerived constructor: void ImpADerived_ctor (struct ImpADerived* _this) { _this->_base->_base.execute = ImpADerived_execute; … } continued in the next page Class Userhold Actually,ituse...
  13. 13. “Virtual” Functions in Pure C (2/2) In C, virtual functions can be achieved via pointer manipulation: The following is how we implement ImpADerived’s execute(): BOOL ImpADerived_execute (struct Interface* _this) { // here we can check _this->mType to confirm struct version first struct ImpADerived* _this2 = (struct ImpADerived*)_this; _this2->doMoreThings(_this2); … } So just like what we did in C++ virtual, for general Interface users: void func(struct Interface* pInterf) { pInterf->execute(pInterf); } struct ImpADerived a; ImpADerived_ctor(&a); func((struct Interface*)&a); Inside func(), ImpADerived::execute() is used instead of Interface::execute() Now we achieve the same functionality in C as in C++ Class Userhold Actually,ituses...
  14. 14. Reference & Appendix ● Appendix: ○ Sample code on GitHub: https://github.com/YosenChen/SoftwareArchitecture Design/tree/master/OOLikeC-2 ○