summaryrefslogtreecommitdiffstats
path: root/C++/Multiple Inheritance/MultiInheritance.cpp
blob: 4ddaf21dfe75bdffe03b93096cece0cd2f5830d9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
// Name: msglm
// Date: Nov-7th-2022
// Program Name: Multiple Inheritance
// Description: Toying around with inheritance by making a program that calculates the only thing worse than OOP: politics.


//My last project got some marks off for my parent class doing nothing, and i'll admit, that was the case! My parent class was a glorified struct and might have been a bit too sensible to be considered OOP.
//So, this time around, im going to channel my inner Java developer and make an abomination example that both fulfills the rubric AND provides some examples for why OOP should be tossed into the trash.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

//Classes


//This person class refers to only one aspect of a person: their ability to pay taxes, however, objects in reality are much more complex than this.
//I can foresee someone modifying this person class with much more, such as the ability to eat, drink, read, work, etc. and this thing "person" becoming
//more feature complete as time goes on depending on what's necessary. This isn't a bad thing, however, when combined with inheritance it leads to disaster.
//
//Even if you have a conventional subclass of person and not a strange one (i.e my company subclass), you will create a very bloated being. One of my subclasses is a 
//politician. Right now, this is a sensible decision as a politician's taxes may become important in the program later on, however, if the person class keeps getting 
//more and more bloated, this may become absurd. A politician eating or drinking, doesn't really matter depending on the scope of the program. If this was a small government
//simulator, it'd be unnecessary to cruft up the politician class with junk about eating if the politician class only needs certain aspects of the person class.
//
//This can be solved with intelligent programming of everything on your system, but assuming that your development team is perfect is just a bad idea and assuming you can keep track of everything going on in a big project is a worse idea.
class person {
    public:
        float calculateTax() {
            if (alive) {
                return income*taxRate;
            } else {
                //The dead can't pay taxes!
                //
                //...well they can with death tax, but
                //I don't feel like thinking about that kind
                //of government overreach, especially in an assignment
                //meant to make fun of OOP, not the government.
                return 0;
            }
        }

        //I don't like metaprogramming, but things like this are why it exists
        void setIncome(float i) { income = i; }
        void setAlive(bool i) { alive = i; }
        void setTaxRate(float i) { taxRate = i; }
        void setName(string i) { name = i; }
        float getIncome()  { return income;}
        bool getAlive()    { return alive;}
        float getTaxRate() { return taxRate;}
        string getName() { return name;}
    private:
        float income;
        bool alive;
        float taxRate;
        string name;
};

//Some people say that the legal rights of companies encroach on the point of
//personhood, especially after Citizens United v. Federal Election Commission.
//Due to this, it's concievable that in some program, somewhere, someone will
//inheirt a company from a person despite them being very different things in reality.
//
//This serves as an example of why the class-based way of thinking can rationalize very stupid things:
//A company is not a person and doesn't act like a person by conventional reasoning, however, using
//particular and contextual reasoning, reasoning that may only exist in the programmers mind, you can
//justify incredibly stupid inheritence like this. 
//Of course, this example is almost absurd, but you can see the idea here. I don't know how many times i've seen people
//attempt to make the "player" a subclass of a generic belligerent class when developing an RPG game. Every single time
//it leads to the player class being an overbloated abomination due to both being developed and added upon to account for 
//niche circumstances. By the end, the player and the generic belligerent class don't even remotely resemble eachother. 
class company: public virtual person {
    public:
        void cleverAccounting() {
            if(hasAccountant) {
                organizationTaxableIncome = calculateTax()*0.5;
            } else if (hasLawyer) {
                organizationTaxableIncome = calculateTax();
            } else {
                taxDelinquent = true;
                organizationTaxableIncome = calculateTax()*2;
            }
        }
        void setHasAccountant(bool i) { hasAccountant = i; }
        void setTaxDelinquent(bool i) { taxDelinquent = i; }
        void setHasLawyer(bool i) { hasLawyer = i; }
        void setOrganizationTaxableIncome(float i) { organizationTaxableIncome = i; }
        bool getHasAccountant()  { return hasAccountant;}
        bool getTaxDelinquent()    { return taxDelinquent;}
        bool getHasLawyer() { return hasLawyer;}
        float getOrganizationTaxableIncome() { return organizationTaxableIncome;}
    private:
        bool hasAccountant;
        bool taxDelinquent;
        bool hasLawyer;
        float organizationTaxableIncome;

};

//Now, this reasoning is conventional. A politician is a person, but this class will suffer many of the same problems the person class does by being able to be edited to maximize bloat by other programmers. If your programmers aren't editing this, then they're making subclasses that over all just make the program more confusing. Nobody wants to keep up with politician_who_can_eat_and_drink and politician_who_can_eat_and_do_taxes in their program for each niche thing. Either situation is a lose-lose long term.
class politician: public virtual person {
    public:
        void incomeGoesPublic() {
            if (economicPopulist) {
                if (getIncome() > 80000) {
                    publicApproval = publicApproval - 0.3;
                    if (publicApproval < 0.5) {
                        voters = voters - (voters * 0.4);
                    }
                }
            }
        }
        void setPublicApproval(float i) { publicApproval = i; }
        void setVoters(int i) { voters = i; }
        void setEconomicPopulist(bool i) { economicPopulist = i; }
        float getPublicApproval()  { return publicApproval;}
        int getVoters()    { return voters;}
        bool getEconomicPopulist() { return economicPopulist;}
    private:
        float publicApproval;
        int voters;
        bool economicPopulist;

};

//Now here's where we get into "abomination" territory. Some ignorant intern or coding "genius" thinks it's clever to combine some classes together that are far from related to eachother. Maybe both it's because of the functionality both classes have or because they are "related" by some sick mockery of logic and reasoning. These are unfortunately real things that happen in real code bases and, once you get to this level of inheritance and abstration, the final product is far from resembaling the original classes that spawned the whole mess. 
//Just citing the examples you offered, and by no means this is not a dig at you, it's just an example of they type of mindset OOP programming puts people in, "Base class of video games, then 2 derived classes: 1 for mmo and 1 for fps, join class is reviews". Combining a MMO and an FPS conceptually does not give you a review, however, in code this may make absolute sense to do since they're just functions and variables and a review might need access to some data contained with both the FPS and MMO class.
//At this level of abstraction, the notion that object orientated programming refers to "objects" falls aparts in favor of programmer convienence. This is overall harmful to a code base because it creates a misalignment between the intent of a programming paradigm and the actual results in the code. Programmers start by making objects that actually exist and are definable and they end by making "objects" that are either not objects at all, but rather a ball of functions and data, or very strange and tangently related objects that only connect to their parent objects in code, but not actual concept. More often than not, I find this makes it where I am fighting my tools just to do what I want to when dealing with OOP systems.

//This example goes for the latter and preserves some of the "object" aspects of OOP. A political party is an object, it has politicians, and sorta acts like a company. It's not a good connection because a politicalParty is not a person, isn't a subvariant of either a politician or a company, and instead is its own thing with its own defined behavior in reality, however, a politicalParty, in this example, can pay taxes, can have lawyers, can have accountants, can have voters, can have public approval, can be economically populist, can be subject to tax rates, can take in income, and can be alive (or active). In pure code, this object makes sense, in reality, it does not.

//This is the crux of the problem with OOP programming. In reality, it's really not object orientated because structures in code aren't objects and can never be objects. Computers preform tasks on data, so programming should be modeled in a fashion where this is at the front of a programmer's mind. 
//Computers cannot make objects. Objects are capable of being limitlessly applied and used in almost every context. I can take a real soda can and throw it, I can take a real soda can and drink it, and I can take a real soda can and shoot it into the sun. Computers are machines of data input, data processing, and data output that, at their root, use declarative operations to achieve these things. Nowhere in the structure of a computational machine is there a way to create an object that can be accessed and use in limitless ways. All possible activties must be declared before usage. This means that people are incentivized to not add unnecessary traits to the digital objects they create, at least until they drop the perception of OOP as object orientated and start viewing it as functions and data glued together again. 
//This makes OOP, when executed with objects in mind, a cruel mockery of actual objects that will always fall short either in the object's usability or due to out-of-scope, overengineering of an object into an uncomprehendable disaster. The scope of an object must go beyond a program's requirements to be a true object. Anything inherit must be a direct subclass of the object that inherits all aspects of its parent (such as a politician inheriting from a person). In computing, this is just not how the system works, so you end up fighting your tools if you adhere to OOP 100%.
//When OOP is not executed with true objects in mind, it's just a bad way of grouping code and data together that makes life harder. 

class politicalParty: public politician, public company {
    public:
        void determinePoliticalStanding() {
            if(getAlive()) {
                if(getCorrupt()) {
                    cleverAccounting();
                } 

                if(getTaxDelinquent()) {
                    setPublicApproval(getPublicApproval() - 0.3);
                    if (getPublicApproval() < 0.5) {
                        setVoters(getVoters() - (getVoters() * 0.4));
                        cardHoldingMembers = cardHoldingMembers - (cardHoldingMembers * 0.2);
                    }
                }
                incomeGoesPublic();

                if (getOrganizationTaxableIncome() > 10000 && getTaxDelinquent()) {
                    setPublicApproval(getPublicApproval() - 0.2);
                    if (getPublicApproval() < 0.5) {
                        setVoters(getVoters() - (getVoters() * 0.4));
                        cardHoldingMembers = cardHoldingMembers - (cardHoldingMembers * 0.2);
                    }
                }

                if (getVoters() >= 10000 && cardHoldingMembers > 1000 && getPublicApproval() >= 0.5) {
                    currentlyHoldsOffice = true;
                } else {
                    currentlyHoldsOffice = false;
                }


            } else {
                currentlyHoldsOffice = false;
            }

            if (getCurrentlyHoldsOffice()) {
                cout << "The political party " << getName() << " has won the election." << endl;
            } else {
                cout << "The political party " << getName() << " has lost the election." << endl;
            }
            cout << getName() << " had a total of " << getVoters() << " voters supporting it and an approval rating of " << getPublicApproval()*100 << "%\n";
        }
        void setCurrentlyHoldsOffice(bool i) { currentlyHoldsOffice = i; }
        void setCorrupt(bool i) { corrupt = i; }
        void setCardHoldingMembers(int i) { cardHoldingMembers = i; }
        bool getCurrentlyHoldsOffice()  { return currentlyHoldsOffice;}
        bool getCorrupt()    { return corrupt;}
        int getCardHoldingMembers() { return cardHoldingMembers;}
    private:
        bool currentlyHoldsOffice;
        bool corrupt;
        int cardHoldingMembers;
};


politicalParty inputParty() {
    politicalParty party;
    string temp;


    cout << "===Enter information about a political party===\n";
    cout << "Is this party active? (y/n): ";
    cin >> temp;
    if(temp == "y" || temp == "Y") {
        party.setAlive(true);
    } else {
        party.setAlive(false);
    }

    cout << "What is this party's name? ";
    cin.ignore();
    getline(cin, temp);
    party.setName(temp);

    cout << "What is this party's overall income? ";
    cin >> temp;
    party.setIncome(stof(temp));

    cout << "Political parties in this country pay taxes.\n";
    cout << "What is the tax rate the party is subject to (as a decimal-notation percentage)? ";
    cin >> temp;
    party.setTaxRate(stof(temp));

    cout << "Does this political party have an accountant (y/n)? ";
    cin >> temp;
    if(temp == "y" || temp == "Y") {
        party.setHasAccountant(true);
    } else {
        party.setHasAccountant(false);
    }

    cout << "Does this political party have a lawyer (y/n)? ";
    cin >> temp;
    if(temp == "y" || temp == "Y") {
        party.setHasLawyer(true);
    } else {
        party.setHasLawyer(false);
    }

    cout << "Is this party's policy economically populist (y/n)? ";
    cin >> temp;
    if(temp == "y" || temp == "Y") {
        party.setEconomicPopulist(true);
    } else {
        party.setEconomicPopulist(false);
    }

    cout << "Is this party politically corrupt(y/n)? ";
    cin >> temp;
    if(temp == "y" || temp == "Y") {
        party.setCorrupt(true);
    } else {
        party.setCorrupt(false);
    }

    cout << "What is the current public approval rating of the party (as a decimal-notation percentage) (50 percent approval or higher is necessary to win)? ";
    cin >> temp;
    party.setPublicApproval(stof(temp));

    cout << "How many people will be voting for this party? (10k are necessary to win) ";
    cin >> temp;
    party.setVoters(stoi(temp));

    cout << "How many people are members of the party (1k are necessary to win) ";
    cin >> temp;
    party.setCardHoldingMembers(stoi(temp));

    return party;
}

int main() {
    politicalParty userParty = inputParty();
    userParty.determinePoliticalStanding();
}

/*
   This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License Version 3 ONLY as published by the Free Software Foundation.

   This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License along with this program.  If not, see <https://www.gnu.org/licenses/>.
   */