How to access a non static method in an abstract class's static method?

Re: basketball bet program

  • QUESTION: Hi Zlatko once again, This program involves calculating winnings/losses for basketball bets where the betting company adds the following bonus percentages to the winnings. 0.5% bonus for winnings of $200 or less, 1% to winnings of 200.01 to $1500, and 1.5% for 1500.01 or more. Win 90% of bet when picking the correct winner, else lose the bet. For example, if the bet is $100, the bettor wins $90 if correct or loses $100 if wrong. The two teams wer'e looking at are named Shamrocks and Shakers. There are also other bet types I need to include in this program, but I'm only doing this first one (as the rest should be similar after I finally get this one working) Also, program should be using virtual functions including at least one pure virtual function with polymorphism. And also one class for each bet type with a base class containing appropriate data members and methods should also be included. Here's where my program is at the moment, don't want to get too far ahead of myself. Is this right --> virtual functions allow you to reuse code but change it as necessary. For example, a building class may have a function for building a gray house. Now a apartment class (derived) from building class the apartment may need three windows and a door. This is then where we can use virtual functions? And pure virtual function, they do the same except it's an empty function with nothing in the body? But why you want to do that? That I'm a little confused. Finally, I wanted to write the calcBonus so that it appears only once, meaning, I have the function already used once, and for the rest of the bet types, I would simply recall this function as the you always calculate the Bonus with the same formula set. Thank you very much! using namespace std; class Bet { public: Bet(const char*, const char*); ~Bet(); virtual float calcBonus() const = 0; virtual void print() const; private: char *firstTeam; char *secondTeam; float betAmt; }; Bet::Bet(const char *firstTeam_name, const char { firstTeam = new char[strlen(firstTeam_name) + 1]; strcpy(firstTeam, firstTeam_name); secondTeam = new char[strlen(secondTeam_name) + 1]; strcpy(secondTeam, secondTeam_name); } void Bet::print() const { cout = 200.01 && betResult = 1500.01) return 1.5/100 * betResult; } int main() { Winner w("Shakers", 90, "Shamrocks", 88, 100); return 0; } ANSWER: Hello Mike. Virtual functions allow you to write code that uses some base class. At run time, you can pass a derived class to that code, and when that code calls virtual methods, it is code in the derived classes that gets executed. I explain this in more detail, and with code samples at this page: https://sites.google.com/site/zlatkoscodingtopics/virtual-function-basics When you have inheritance, the behavior of method calls changes depending on if you are calling the base version of a class, the derived version of a class, or if you are calling through a base reference or a derived reference. Adding virtual functions complicates it even more. The best way to learn is to create a base and derived class with some methods and access them in different ways. Below is such a program. I've included comments about which method is called, and why. It is important that you understand each case. using namespace std; class Base { public: void a() { cout virtual void va() { cout }; class Derived : public Base { public: void b() { cout }; int main(void) { Base b; Derived d; // The comments show the output b.a(); // Base::a because b is a Base instance b.b(); // Base::b because b is a Base instance b.va(); // Base::va because b is a Base instance b.vb(); // Base::vb because b is a Base instance cout d.a(); // Base::a because Derived does not have an a d.b(); // Derived::b because d is an instance of Derived d.va(); // Base::va because Derived does not have a va d.vb(); // Derived::vb because d is an instance of Derived cout Base& br = d; // assign a Derived instance to a Base reference br.a(); // Base::a for the same reason as the br.b() example below. Also // Derived does not have an a method. br.b(); // Base::b Although the actual type is derived, // the b method is non virtual, and is being // called through a base reference, so the Base version of b is called. br.va(); // Base::va, because Derived does not have a va. br.vb(); // Derived::vb. Because vb is virtual, and the actual type is Derived, // it is the Derived vb that is called // even though we are calling it through a Base reference. // Compare this behaviour with the call of br.b(). // The above example is the purpose of virtual functions cout } The way you describe virtual functions when you say: "Is this right --> virtual functions allow you to reuse code but change it as necessary." is true, but not much different from non virtual functions. For example, in the above code, I have non-virtual methods "a" and "b" in Base, which can be reused in Derived, but Derived changes method "b" by supplying its own. The real power of virtual functions is in accessing a derived class' method through a base class reference (or a base class pointer). Pure virtual functions are like virtual functions but they require a derived class to provide an implementation. Often, the base class is used like an interface to all the derived objects. In such cases, the Base class will not have any data, and so it would not be logical for the Base class to provide an implementation of the virtual functions. If your calcBonus function is really the same across all bet types, then you can put it into your Bet base class as a virtual method and all others will inherit it. If there is a Loser bet type, then you would probably want to override the calcBonus implementation in the Loser bet. It might make sense to make the print method pure virtual to require each Bet type to provide an implementation. I hope that helps you understand the purpose of virtual functions. This has been a long answer for me, and actually quite a challenging one so I hope it is clear. Please do ask again about anything that is unclear. ---------- FOLLOW-UP ---------- QUESTION: Hi Zlatko, Thanks for the explanation, I guess though, it would take some more practice to get everything straight. Sorry if I sound a little confused at times, because this stuff is not exactly a walk in the park for me so to say. Anyway, as per my assignment here (See code below) I sort of rewrote it a bit renamed some of the variables and now, I do have a virtual function calcBonus defined in the base class and I have a the calcBonus function there too. Assuming I am on the right track here, as far as I see, the problem is where I may get the calcBetResult information from because I understand the calcBonus if statements can't do the proper calculations. This calcBetResult, would be the Bet calculation (for this one bet type I described above (which I will call the Winner bet type), the winning 90% of bet if the team you bet on wins else you lose all your money). I see that getting this fixed would then allow me to just say Bet::calcBonus in a derived class, and it would just go to the base class and use the calcBonus function that is already defined there (As you use the same formula every time you need to Calculate the Bonus.) And also, I'm not getting something --> how would you actually send the parameters properly out to the part of my code where I want to compare the team names so if the winning team's name is the same as the name of the team I betted on (in other words, I have picked the winner), the calculation for my winnings would take place, else I'd do the other calculation (the losing side). Here, I wanted to send in the team names, but I have a feeling we need to get it from above, or I'm doing something wrong or is there a better way of it that's not as confusing? Thanks once again! Mike using namespace std; class Bet { public: Bet(const char *, const char *); ~Bet(); virtual float calcBetResult() const = 0; virtual float calcBonus() const; virtual void print() const; private: char *team1; char *team2; }; Bet::Bet(const char *team1_name, const char *team2_name) { team1 = new char[strlen(team1_name) + 1]; strcpy(team1, team1_name); team2 = new char[strlen(team2_name) + 1]; strcpy(team2, team2_name); } float Bet::calcBonus() const { if(calcBetResult = 200.01 && calcBetResult = 1500.01 && calcBetResult = 7500.01) return 2 / 100 * calcBetResult; } void Bet::print() const { cout << team1 << ' ' << team2; //need to add more stuff to here, we're not only printing team names! } Bet::~Bet() { delete[] team1; delete[] team2; } class Winner: public Bet { public: Winner(const char*, int, const char*, int, const char*, float = 0.0); virtual float calcBonus() const; virtual float calcBetResult() const; virtual void print() const; private: float WinnerBetAmt; }; Winner::Winner(const char *team1_name, int team1_score, const char *team2_name, int team2_score, const char :Bet(team1_name, team2_name) { WinnerBetAmt = betAmt; } float Winner::calcBetResult(/*const char *team1_name, int team1_score, const char *team2_name, int team2_score, const char *team_picked, float betAmt*/) const { if((strcmp(team1_name, team_picked) == 0) || (strcmp(team2_name, team_picked) == 0)) return 90 / 100 * WinnerBetAmt; else if((strcmp(team1_name, team_picked) != 0) || (strcmp(team2_name, team_picked) != 0)) return -WinnerBetAmt; } int main() { cout << fixed << showpoint << setprecision(2); Winner w("Shakers", 90, "Shamrocks", 88, "Shakers", 100.00); return 0; }

  • Answer:

    Hello Mike. Thank you for sending me the complete assignment text. It makes things much clearer. I now understand that the Winner bet is a type of betting scheme, and not a win vs. loss, so things are much clearer. You are on the right path. I would make these suggestions. 1) Put all the data into the base Bet class as protected, so that the derived classes can access it. This means teams, scores, and winning team. I suggest you use the std::string datatype instead of character arrays. It is safer, simpler (less code = fewer chances for bugs), and more professional. 2) Each bet type has a different payoff calculation algorithm, so that must be a pure virtual method in the Bet class. You were on the right path. The base Bet class does not know about how to calculate payoff. Each derived class will access the data in the Bet class to determine payoff. You can actually put the payoff as a data member in the base Bet class since every bet has a payoff of some sort. 3) You can put the print method into the base class, because all the data that will be printed is in the base class, and also the printout is the same for all bet types with the exception that the text for the bet type is not known by the base class. You need a virtual function which will return the text of the bet type to the print method. You can make it a pure virtual as well. 4) The calcBonus function is not virtual and is common to all bets. You were on the right to make it common in the base class. It is called upon by the derived classes when the bet payoff is positive. It only depends on the winnings. I would pass the winnings to it as a parameter. If you do that, you will see that calcBonus does not need any other data, and so can be made static. If you are not familiar with static methods, don't worry about it. The assignment does not say that you need virtual functions and at least 1 pure virtual. In my opinion, that means that all virtual function can be pure virtual, but if you want at least one that is not pure virtual, you can make the betName method virtual, but not pure. With these suggestions, your declarations look like this: class Bet { public: Bet(const std::string& team1, int score1, const std::string& team2, int score2, float betAmount, const std::string& winningTeam); // dont need this anymore ~Bet(); // this will calculate and set mWinnings, no return type is needed virtual void calcBetResult() = 0; // derived class to supply algorithm virtual const char* betName() const = 0; void print() const; static float calcBonus(float winning); protected: // These data members will be visible to derived classes std::string mTeam1; int mScore1; std::string mTeam2; int mScore2; std::string mWinningTeam; float mBetAmount; float mWinnings; }; class Winner: public Bet { public: Winner(const std::string& team1, int score1, const std::string& team2, int score2, float betAmount, const std::string& winningTeam); virtual void calcBetResult(); virtual const char* betName() const { return "Winner";} };

Miningco.com Visit the source

Was this solution helpful to you?

Related Q & A:

Just Added Q & A:

Find solution

For every problem there is a solution! Proved by Solucija.

  • Got an issue and looking for advice?

  • Ask Solucija to search every corner of the Web for help.

  • Get workable solutions and helpful tips in a moment.

Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.