Thread: My first steps in objective oriented programming. Why/How to overload a function?

  1. #1
    Registered User
    Join Date
    May 2008
    Posts
    115

    My first steps in objective oriented programming. Why/How to overload a function?

    Hello all,

    here is my first attempt at object oriented programming in cpp, a goofy duel game.

    Below my first implementation.

    What I am stuck with is this:

    There can be potentially many weapon functions, each taking a different number of arguments. The output is always an integer (damage).

    Since a player has two arms only, and I would like to assign a weapon function to each arm at initialization, effectively creating a load out. It should be possibly to leave an arm empty, say, because rifle is a two-handed weapon and assigning rifle to one arm should leave the other unused (default output zero).

    So I would then like to iterate over both arms to get damage output from each one (unlike now, where the weapon function is not related to the player). What I am aiming at something like this

    Code:
    p1.health = p1.health - p2.leftarm(p2.skill, duelrange) - p2.rightarm(p2.skill, duelrange);
    p2.health = p2.health - p1.leftarm(p1.skill, duelrange) - p1.rightarm(p1.skill, duelrange);
    If a function is not initialized then I should return a zero integer.

    I tried to defines a struct that inherits a player and overloads the two functions with. Did not really work (but I guess I will be able to debug it). But it bothers me that another struct is needed simply to insert two functions at initialization?

    Can you please explain how to best code this?

    Code:
    #include <iostream>
    #include <string>
    #include <time.h>
    
    using std::cin;
    using std::cout;
    using std::endl;
    using std::string;
    
    struct player
    {
    	string name;
    	int health;
    	int skill;
    	// virtual void lefthand() = 0;
    	// virtual void righthand() = 0;
    };
    
    int pistol(int accuracy, int range) {
    	int dmg = 0;
    	int shortrange = 50;
    
    	if (range <= shortrange) accuracy = accuracy + 1;
    
    	int d6 = rand() % 6 + 1; // roll d6
    	if (d6 >= accuracy) dmg = 15; // hit
    
    	return dmg;
    }
    
    int rifle(int accuracy, int range) {
    	int dmg = 0;
    
    	int d6 = rand() % 6 + 1; // roll d6
    	if (d6 >= accuracy) dmg = 25; // hit
    
    	return dmg;
    }
    
    void print(player a, player b)
    {
    	cout << a.name << "(" << a.health << ") vs " << b.name << "(" << b.health << ")" << endl;
    }
    
    int main()
    {
    	srand((unsigned int) time(NULL));
    	player p1{"Joe", 50, 3};
    	player p2{"Jim", 50, 3};
    	print(p1, p2);
    
    	int duelrange = 100;
    
    	while (p1.health > 0 and p2.health > 0)
    	{
    		p1.health = p1.health - rifle(p2.skill, duelrange);
    		p2.health = p2.health - pistol(p1.skill, duelrange);
    		print(p1, p2);
    	}
    
    	if (p1.health <= 0)
    	{
    		cout << p2.name << " kills " << p1.name << endl;
    	}
    	else {
    		cout << p1.name << " kills " << p2.name << endl;
    	}
    
    	cin.get();
    	return 0;
    }

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by serge
    There can be potentially many weapon functions, each taking a different number of arguments. The output is always an integer (damage).
    Instead of many weapon functions, consider defining a weapon class. You can then have two weapon objects per player, each representing a weapon in one hand. You would have a single function that takes a weapon object as an argument in order to use the given weapon.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Also, post your attempt with the multiple structures you were talking about.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  4. #4
    Registered User
    Join Date
    May 2008
    Posts
    115
    Quote Originally Posted by phantomotap View Post
    Also, post your attempt with the multiple structures you were talking about.
    OK, I admit that I did not get very far - it became complicated fast.

    Below my attempt to put a skeleton with generic and derived classes. In particular, I could not pass more than one weapon to the Player's constructor. So I thought I would need to create each individual combination of weapons as a loadout struct, which is certainly not necessary. For example, this would not compile:

    Code:
    Player(string n = "", string t = "", string rightw = "", string leftw = "") : Man(t), Weapon(rightw), Weapon(leftw), name(n) {}
    Full example:

    Code:
    #include <iostream>
    #include <string>
    
    using std::cout;
    using std::endl;
    using std::string;
    
    class Man
    {
    	public:
    	string mtype;
    	Man(string t = "") : mtype(t) {}
    	virtual void hit();
    };
    
    void Man::hit() {
    	cout << "Man::hit" << endl;
    }
    
    struct Weapon
    {
    	string wtype;
    	Weapon(string t = "") : wtype(t) {}
    	virtual void shot();
    };
    
    void Weapon::shot() {
    	cout << "Weapon::shot" << endl;
    };
    
    class Player : public Man, public Weapon
    {
    	public:
    	string name;
    	Player(string n = "", string t = "", string w = "") : Man(t), Weapon(w), name(n) {}
    	void hit() override;
    };
    
    void Player::hit() {
    	cout << "Player::hit" << endl;
    }
    
    int main()
    {
    	Man a;
    	Player b("Joe", "Cowboy", "Colt");
    	
    	a.hit();
    	b.hit();
    	
    	cout << b.mtype << " " << b.name << endl;
    	cout << b.wtype << endl;
    	return 0;
    }
    Last edited by serge; 08-17-2019 at 04:45 PM.

  5. #5
    Registered User
    Join Date
    May 2008
    Posts
    115
    Please forget my pervious post. I think an array of functions would be best solution. But how can I include Weapons class in the Player class, so that a specific loadout can be chosen when a Player is instantiated? I would like to say that Player a has weapons W1 and W2, or W2 and W2, or W1 alone etc.

    Code:
    class Weapons
    {
    public:
    	int W1(int x, int y) { cout << "W1 dmg:"; return x + y; };
    	int W2(int x, int y) { cout << "W2 dmg:"; return x * y; };
    };
    
    typedef int (Weapons::* ptWeapon)(int, int);
    
    class Player : public Weapons
    {
    public:
    	string name;
    	Player(string n = "") : name(n) {}
    };
    
    int main()
    {
    	ptWeapon Loadout[2] = { NULL };
    
    	Loadout[0] = &Weapons::W1;
    	Loadout[1] = &Weapons::W2;
    
    	Weapons instance;
    	cout << (instance.*Loadout[0])(1, 2) << endl;
    	cout << (instance.*Loadout[1])(3, 2) << endl;
    
    	Player a("Joe");
    	cout << a.name << endl;
    
    	return 0;
    }
    Last edited by serge; 08-18-2019 at 12:57 AM.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Public inheritance typically models an "is-a" relationship. A player has one or more weapons (typically expressed by composition, or more loosely by aggregation/association), so you should not be using inheritance to express the relationship between Player and Weapon(s).

    Why are you so keen on a function for each weapon? Have you decided what are you trying to model for weapons?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    May 2008
    Posts
    115
    Quote Originally Posted by laserlight View Post
    Public inheritance typically models an "is-a" relationship. A player has one or more weapons (typically expressed by composition, or more loosely by aggregation/association), so you should not be using inheritance to express the relationship between Player and Weapon(s).

    Why are you so keen on a function for each weapon? Have you decided what are you trying to model for weapons?
    Probably out of my ignorance (I am a total beginner) it simply appears easier to work with an array of weapons, easier to iterate through a loadout, easier to change a loadout by pointing to a new function.

    One difficulty I see is that each weapon as a function must have the same set of arguments. Can this be relaxed?

    Also, I can do without packing Player and Loadout in one class, I could instantiate and use them separately, keeping track of who has what. At the moment I don’t understand how to insert a Loadout in the constructor of Player.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Let's go back to the concepts that you're trying to express:
    • What's a weapon? What does a weapon have? What does a weapon do? Do weapons exist independently of players such that they are created at program startup and remain fixed after that? Can there be more than one particular weapon?
    • What's a loadout? What does a loadout have? What does a loadout have to do with a player? Can a player have multiple loadouts, and if so, what does that mean? Etc
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    It's time to step back and do some doodling.
    My first steps in objective oriented programming. Why/How to overload a function?-uml1-png

    Create stories for say
    - pick up weapon
    - put down weapon
    - use weapon
    - place into and out of inventory 'backpack'

    So immediately, you can see you have a player, an object and an object container.

    For example, all weapons have a weight and an amount of damage they do.

    Maybe you use the weight to see how much your character is carrying. If they carry too much, it affects skill, hunger, etc.

    Use the damage to determine how effective an attack is.

    Certain weapons may require two handed operation, like a broad sword.
    Certain weapons like spears are effective at a distance. This also means that they're a consumable resource. You can only use each spear once (unless you walk up to it and pick it up again).

    Bullets for a gun on the other hand might be one-time usable only, even if you do find them after the event.

    You don't need fancy tools, just a block of 5x3 post-it notes or library index cards. These you can easily divide into a name, description, methods and variables sections.

    Do your methods and variables support your stories?

    You can "rewrite" the code in a matter of minutes at this level, so you can try out lots of different approaches to see what works for you.

    You don't have to model everything. If you just have the main features of the significant objects in your idea, that will go a long way to guiding your implementation.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    May 2008
    Posts
    115
    I am rethinking the design and getting the hang of manipulating structures. Yes, it got messy with functions once more than a single variable was needed to be returned.

    One question that bothers me is this. If I want to use all variables from Weapon in Player, not just lw.name and rw.name, do they all have to be declared in Player and listed in its constructor?

    Can I not simply say that I want to use any variables of a particular instance of Weapon in Player?

    Code:
    struct Weapon
    {
    	string name;
    	int dice;
    	int str;
    	Weapon(string n = "Weapon", int d = 1, int s = 0) : name(n), dice(d), str(s) {}
    };
    
    struct Player
    {
    	string name;
    	string LWeapon;
    	string RWeapon;
    	Player(string n, const Weapon& lw, const Weapon& rw) : name(n), LWeapon(lw.name), RWeapon(rw.name) {}
    };
    
    int main()
    {
    	Weapon w1("Gun 1", 1, 10);
    	Weapon w2("Gun 2", 1, 10);
    	Weapon w3("Gun 3", 1, 10);
    	Weapon w4("Gun 4", 1, 10);
    
    	Player A("Joe", w1, w2);
    	Player B("Jim", w3, w4);
    
    	cout << A.name << " " << A.LWeapon << " " << A.RWeapon << endl;
    	cout << B.name << " " << B.LWeapon << " " << B.RWeapon << endl;
    
    	return 0;
    }

  11. #11
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    You are passing a weapon into the constructor anyway so just store the weapon within the player structure.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  12. #12
    Registered User
    Join Date
    May 2008
    Posts
    115
    If I do as below, then A.w1 and A.w2 remain at their default values, i.e. with A.w1.name = "Weapon" instead of A.w1.name = "Gun 1". How can I make sure that w1 and w2 get passed to Player with all of their fields?

    Code:
    struct Weapon
    {
        string name;
        int dice;
        int str;
        Weapon(string n = "Weapon", int d = 1, int s = 0) : name(n), dice(d), str(s) {}
    };
     
    struct Player
    {
        string name;
        Weapon w1;
        Weapon w2;
        Player(string n) : name(n) {}
    };
     
    int main()
    {
        Weapon w1("Gun 1", 1, 10);
        Weapon w2("Gun 2", 1, 10);
     
        Player A("Joe");
     
        cout << A.name << " " << A.w1.name << " " << A.w2.name << endl;
    
    }

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Refer to post #11 for the hint:
    Code:
    struct Weapon
    {
        string name;
        int dice;
        int str;
        Weapon(string n = "Weapon", int d = 1, int s = 0) : name(n), dice(d), str(s) {}
    };
     
    struct Player
    {
        string name;
        Weapon LWeapon;
        Weapon RWeapon;
        Player(string n, const Weapon& lw, const Weapon& rw) : name(n), LWeapon(lw), RWeapon(rw) {}
    };
     
    int main()
    {
        Weapon w1("Gun 1", 1, 10);
        Weapon w2("Gun 2", 1, 10);
        Weapon w3("Gun 3", 1, 10);
        Weapon w4("Gun 4", 1, 10);
     
        Player A("Joe", w1, w2);
        Player B("Jim", w3, w4);
     
        cout << A.name << " " << A.LWeapon.name << " " << A.RWeapon.name << endl;
        cout << B.name << " " << B.LWeapon.name << " " << B.RWeapon.name << endl;
     
        return 0;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 09-07-2017, 11:35 AM
  2. Replies: 6
    Last Post: 01-21-2013, 05:08 PM
  3. small programming job VCPP / Object Oriented Programming
    By calgonite in forum Projects and Job Recruitment
    Replies: 10
    Last Post: 01-04-2006, 11:48 PM
  4. does anyone here do programming in objective C
    By Silvercord in forum C++ Programming
    Replies: 7
    Last Post: 03-19-2003, 03:48 PM
  5. Programming Objective C in Mac OSX
    By MacUser in forum A Brief History of Cprogramming.com
    Replies: 1
    Last Post: 10-17-2002, 08:12 AM

Tags for this Thread