Question: Program in C Consider the following C++ code showing the polymorphism feature we want to emulate: class Employee { int age; public: int GetAge() {

Program in C

Program in C Consider the following C++ code showing the polymorphism feature

we want to emulate: class Employee { int age; public: int GetAge(){ return age; } virtual void Speak() 0; virtual double GetPay ()= 0; }; public Employee { class HourlyEmployee : double hourly_rate; doublehours; public: virtual void Speak() { cout Get Pay(); // which functiongets called? Who knows! We can emulate this in C using: 1.A struct Employee, with two member fields: a pointer to vtable (asa void**); and an integer field age. 2. A struct HourlyEmployee, with

Consider the following C++ code showing the polymorphism feature we want to emulate: class Employee { int age; public: int GetAge() { return age; } virtual void Speak() 0; virtual double GetPay () = 0; }; public Employee { class HourlyEmployee : double hourly_rate; double hours; public: virtual void Speak() { cout Get Pay(); // which function gets called? Who knows! We can emulate this in C using: 1. A struct Employee, with two member fields: a pointer to vtable (as a void**); and an integer field age. 2. A struct HourlyEmployee, with four member fields: the same fields as Employee, and doubles hourly rate and hours. 3. A struct Commission Employee, likewise, but with a double sales_amount. 4. Global functions to emulate each of the member functions of the objects: (a) Speak_Hourly which takes an Employee pointer, casts it to a HourlyEmployee pointer, and prints the employee's message; (b) GetPay_Hourly which also takes an Employee pointer and returns the employee's total pay (see below); (c) Construct_Hourly which takes a HourlyEmployee pointer and initializes its fields to their default values, most importantly initializing the objects's vtable pointer (more on this below). and then following some tedious steps to create variables of our types and call the appropriate functions: 1. To make a HourlyEmployee, declare a HourlyEmployee variable (either on the stack or with malloc) and then pass it by pointer to Construct_Hourly. 2. To use "subtype polymorphism to point an Employee at a HourlyEmployee, declare an Employee pointer and initialize it by casting your HourlyEmployee's address to an Employee pointer. 3. To use "dynamic dispatch, dereference the Employee pointer's vtable pointer, index the table to the appropriate method, cast that pointer to the correct function pointer type, and invoke the method by passing the Employee pointer and any other necessary parameters. Easy! Vtables A vtable (short for virtual table) is a table of function pointers, with one entry in the table for each virtual function in a class (or its ancestors). Since the Employee class has two virtual functions, the vtable for any Employee-derived object will have two pointers in it for Speak and Get Cost, plus additional entries for any more virtual functions introduced by the derived class. C++ handles the creation and use of vtables automatically; in this lab, we will simulate the work that a C++ compiler performs to transform virtual method calls into vtable lookups. Suppose we have two functions: void Speak_Hourly(struct HourlyEmployee*) and double GetPay_Hourly (struct HourlyEmployee*). We can build a "table" (really an array) of two pointers to functions as such: void* Vtable_Hourly[2] {Speak_Hourly, GetPay_Hourly}; The void* type in C lets us create a pointer to anything, but the compiler won't help us use such a pointer; we will need to cast it to something specific in order to use it. Suppose we have a struct HourlyEmployee h variable that we want to call Speak_Hourly on, but we don't want to use Speak_Hourly directly - instead, we want to use Vtable_Hourly. We note that the first entry in Vtable_Hourly is a pointer to Speak_Hourly, and thus try to use that pointer to call the function it points to: Vtable_Hourly[0]((struct HourlyEmployee *)&h); This makes sense in our head: the element 0 of Vtable_Hourlyis a pointer to Speak_Hourly, which wants a single parameter of type struct Employee *. Unfortunately C sees Vtable_Hourly[O] as a pointer to void, not to a function; we have to tell the compiler that it actually points to a function that returns void and takes a single parameter of type struct Employee *. A cast will accomplish this task: ((void (*) (struct Employee*))Vtable_Hourly [0])((struct Employee *)&h); 1 which tells the compiler to invoke the function pointed to by Vtable_Hourly[0], passing it the address of h as its parameter. Success! All we need to do now is add a new member variable to our structs: a void** pointer to a vtable appropriate to the class. Create one vtable variable globally for all derived Employee types, point the vtable pointers to the appropriate global tables in constructor methods, and voila! We can now call a virtual function through a base class pointer by accessing the appropriate index from the vtable associated with the variable and invoking that function by hand. Program Implement the following code: 1. Create Employee, HourlyEmployee, and CommissionEmployee structs as described above. The first member of each struct should be a void** vtable variable. 2. Implement the Speak_Hourly and Speak_Commission functions for the HourlyEmployee and CommissionEmployee structs as global functions. 3. Add HourlyEmployee and CommissionEmployee implementations of a GetPay function, which takes an Employee pointer and returns a double as such: (a) The pay for an hourly employee is the number of hours multiplied by their hourly rate. (b) The pay for a commission employee is 10% of their total sales, plus 40,000. 4. Create a Vtable_XX global array for each employee derived type, initialized with pointers to the appropriate Speak and GetPay functions for that type, in that order. 5. Implement Construct_xx functions for HouryEmployee and CommissionEmployee, which initialize the member variables to 0 values, and most importantly, sets the employee's vtable pointer to the appro- priate global Vtable_XX variable. (Don't overthink this. It's as easy as writing parameter->vtable = Vtable_Hourly;, for example.) 6. Add a new "class SeniorSalesman, which "derives from CommissionEmployee by duplicating all of CommissionEmployee's member variables. SeniorSalesman will override the GetPay method but will use Commission Employee's version of Speak. Create a vtable and constructor for the SeniorSalesman class, and a GetPay method that returns 20% of the salesman's sales, plus 50,000, plus another 5% of sales if the employee is at least 40 years old. Then write a main program that does the following: 1. Declare an Employee pointer. 2. Ask the user to choose either an hourly employee, a commission employee, or a senior salesman. 3. Use malloc to create space for the appropriate employee, for example, Hourly Employee *h = (HourlyEmployee*)mall (a) Ask the user how old the employee is. (b) If the user selects an hourly, ask them for the employee's pay rate and hours. (c) If the user selects a commission or a senior salesman, ask for the employee's amount of sales. (d) Use your Construct function to initialize the memory given back from malloc, passing the appropriate parameters for the type selected. (e) Point your Employee to the variable. (f) Past this point of the program, you can have no code referring to CommissionEm- ployee, HourlyEmployee, or SeniorSalesman explicitly - everything must be through Employee pointers. 4. Tell the Employee to speak, then inform the user how much money they make. (a) To do this, you will access the vtable pointer from the Employee pointer in your main, index it to the appropriate position for each function, cast that pointer as described above, and invoke the function it is pointing to. Consider the following C++ code showing the polymorphism feature we want to emulate: class Employee { int age; public: int GetAge() { return age; } virtual void Speak() 0; virtual double GetPay () = 0; }; public Employee { class HourlyEmployee : double hourly_rate; double hours; public: virtual void Speak() { cout Get Pay(); // which function gets called? Who knows! We can emulate this in C using: 1. A struct Employee, with two member fields: a pointer to vtable (as a void**); and an integer field age. 2. A struct HourlyEmployee, with four member fields: the same fields as Employee, and doubles hourly rate and hours. 3. A struct Commission Employee, likewise, but with a double sales_amount. 4. Global functions to emulate each of the member functions of the objects: (a) Speak_Hourly which takes an Employee pointer, casts it to a HourlyEmployee pointer, and prints the employee's message; (b) GetPay_Hourly which also takes an Employee pointer and returns the employee's total pay (see below); (c) Construct_Hourly which takes a HourlyEmployee pointer and initializes its fields to their default values, most importantly initializing the objects's vtable pointer (more on this below). and then following some tedious steps to create variables of our types and call the appropriate functions: 1. To make a HourlyEmployee, declare a HourlyEmployee variable (either on the stack or with malloc) and then pass it by pointer to Construct_Hourly. 2. To use "subtype polymorphism to point an Employee at a HourlyEmployee, declare an Employee pointer and initialize it by casting your HourlyEmployee's address to an Employee pointer. 3. To use "dynamic dispatch, dereference the Employee pointer's vtable pointer, index the table to the appropriate method, cast that pointer to the correct function pointer type, and invoke the method by passing the Employee pointer and any other necessary parameters. Easy! Vtables A vtable (short for virtual table) is a table of function pointers, with one entry in the table for each virtual function in a class (or its ancestors). Since the Employee class has two virtual functions, the vtable for any Employee-derived object will have two pointers in it for Speak and Get Cost, plus additional entries for any more virtual functions introduced by the derived class. C++ handles the creation and use of vtables automatically; in this lab, we will simulate the work that a C++ compiler performs to transform virtual method calls into vtable lookups. Suppose we have two functions: void Speak_Hourly(struct HourlyEmployee*) and double GetPay_Hourly (struct HourlyEmployee*). We can build a "table" (really an array) of two pointers to functions as such: void* Vtable_Hourly[2] {Speak_Hourly, GetPay_Hourly}; The void* type in C lets us create a pointer to anything, but the compiler won't help us use such a pointer; we will need to cast it to something specific in order to use it. Suppose we have a struct HourlyEmployee h variable that we want to call Speak_Hourly on, but we don't want to use Speak_Hourly directly - instead, we want to use Vtable_Hourly. We note that the first entry in Vtable_Hourly is a pointer to Speak_Hourly, and thus try to use that pointer to call the function it points to: Vtable_Hourly[0]((struct HourlyEmployee *)&h); This makes sense in our head: the element 0 of Vtable_Hourlyis a pointer to Speak_Hourly, which wants a single parameter of type struct Employee *. Unfortunately C sees Vtable_Hourly[O] as a pointer to void, not to a function; we have to tell the compiler that it actually points to a function that returns void and takes a single parameter of type struct Employee *. A cast will accomplish this task: ((void (*) (struct Employee*))Vtable_Hourly [0])((struct Employee *)&h); 1 which tells the compiler to invoke the function pointed to by Vtable_Hourly[0], passing it the address of h as its parameter. Success! All we need to do now is add a new member variable to our structs: a void** pointer to a vtable appropriate to the class. Create one vtable variable globally for all derived Employee types, point the vtable pointers to the appropriate global tables in constructor methods, and voila! We can now call a virtual function through a base class pointer by accessing the appropriate index from the vtable associated with the variable and invoking that function by hand. Program Implement the following code: 1. Create Employee, HourlyEmployee, and CommissionEmployee structs as described above. The first member of each struct should be a void** vtable variable. 2. Implement the Speak_Hourly and Speak_Commission functions for the HourlyEmployee and CommissionEmployee structs as global functions. 3. Add HourlyEmployee and CommissionEmployee implementations of a GetPay function, which takes an Employee pointer and returns a double as such: (a) The pay for an hourly employee is the number of hours multiplied by their hourly rate. (b) The pay for a commission employee is 10% of their total sales, plus 40,000. 4. Create a Vtable_XX global array for each employee derived type, initialized with pointers to the appropriate Speak and GetPay functions for that type, in that order. 5. Implement Construct_xx functions for HouryEmployee and CommissionEmployee, which initialize the member variables to 0 values, and most importantly, sets the employee's vtable pointer to the appro- priate global Vtable_XX variable. (Don't overthink this. It's as easy as writing parameter->vtable = Vtable_Hourly;, for example.) 6. Add a new "class SeniorSalesman, which "derives from CommissionEmployee by duplicating all of CommissionEmployee's member variables. SeniorSalesman will override the GetPay method but will use Commission Employee's version of Speak. Create a vtable and constructor for the SeniorSalesman class, and a GetPay method that returns 20% of the salesman's sales, plus 50,000, plus another 5% of sales if the employee is at least 40 years old. Then write a main program that does the following: 1. Declare an Employee pointer. 2. Ask the user to choose either an hourly employee, a commission employee, or a senior salesman. 3. Use malloc to create space for the appropriate employee, for example, Hourly Employee *h = (HourlyEmployee*)mall (a) Ask the user how old the employee is. (b) If the user selects an hourly, ask them for the employee's pay rate and hours. (c) If the user selects a commission or a senior salesman, ask for the employee's amount of sales. (d) Use your Construct function to initialize the memory given back from malloc, passing the appropriate parameters for the type selected. (e) Point your Employee to the variable. (f) Past this point of the program, you can have no code referring to CommissionEm- ployee, HourlyEmployee, or SeniorSalesman explicitly - everything must be through Employee pointers. 4. Tell the Employee to speak, then inform the user how much money they make. (a) To do this, you will access the vtable pointer from the Employee pointer in your main, index it to the appropriate position for each function, cast that pointer as described above, and invoke the function it is pointing to

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!