#include // In this program, we try to achieve a kind of OOP-style abstraction // in C. // The idea is that we have two different kinds of bank accounts, savings // and checkings, each with unique features. Checking accounts have a "fee" // that's charged for withdraws and savings accounts have a "bonus" for // deposits. The "methods" withdraw/deposit, etc... must therefore be // different for each type of account. However, sometimes we really don't // care about the type of the account, but would just like to treat them // in a generic way. typedef struct accstruct * account; struct accstruct { unsigned char actype; // type of account: 0 for savings, 1 for checking int balance; union { // a "union" contains one or the other of its members: int bonus; // for savings int fee; // for checking } extra; }; // shared function for all account types. int inquiry(account A) { return A->balance; } // savings account withdraw: void s_withdraw(account A, int amt) { A->balance =A->balance - amt; } // checking account withdraw void c_withdraw(account A, int amt) { A->balance = A->balance - amt - A->extra.fee; } void s_deposit(account A, int amt) { A->balance =A->balance + amt + A->extra.bonus; } void c_deposit(account A, int amt) { A->balance = A->balance + amt; } // For genericity, define dispatch function (also called proxy) void withdraw(account A, int amt) { if (A->actype==0) s_withdraw(A,amt); else if (A->actype==1) c_withdraw(A,amt); } void deposit(account A, int amt) { if (A->actype == 0) s_deposit(A,amt); else if (A->actype == 1) c_deposit(A,amt); } /* A better way to dynamically dispatch to the correct function is to set up a dispatch vector, which is in fact what a C++ compiler does. typedef void (*method)(account,int); method Withdraw[2]; void withdraw(account A, int x) { Withdraw[A->tag](A,x); } //... Withdraw[0] &withdraw0; Withdraw[1] = &c_withdraw; */ // constructor for savings account account newsavings(int bal, int bn) { account A = (account)malloc(sizeof(struct accstruct)); A->actype = 0; A->balance = bal; A->extra.bonus = bn; return A; } // constructor for checking account: account newchecking(int bal, int f0) { account A = (account)malloc(sizeof(struct accstruct)); A->actype = 1; A->balance = bal; A->extra.fee = f0; return A; } int main(int argc, char **argv) { account savings = newsavings(500,1); account checking = newchecking(1000,2); deposit(savings,50); withdraw(checking,200); printf("savings balance is %d\n",inquiry(savings)); printf("checking balance is %d\n",inquiry(checking)); checking->balance = 0; // he he he ... exit(0); } /* problems solved: Declaring variables of different account types using one static type. Defining single functions for withdraw/deposit problems remaining: no encapsulation (everything is public) : not extensible *** not scalable : cumbersome to program */