-1

I have looked at other forum posts and I am still confused. I am very new to coding so a simple answer would be appreciated. I am trying to create a simple program that uses sets and gets to set the player's attributes and then gets them with functions. However, whenever I call the functions I get the error.

Here is my .h file:

#pragma once

#include <iostream>
#include <dos.h>
#include <string>
#include <sstream>
using namespace std;

class Player
{
    private:
        string name;
        int health;
        int strength;
        int stamina;
        int experience;
        bool passive;
    public:
        string GetName();
        string SetName(string tName);
        int GetHealth();
        int SetHealth(int tHealth);
        int GetStrength();
        int SetStrength(int tStrength);
        int GetStamina();
        int SetStamina(int tStamina);
        int GetExperience();
        int SetExperience(int tExperience);
        bool GetPassive();
        bool SetPassive(bool tPassive);
};

And here is my 1st then 2nd cpp file:

#include <iostream>
#include <iostream>
#include <dos.h>
#include <string>
#include <sstream>
#include "C:\\Users\\Ryan Bell\\Desktop\\School\\2nd Year\\Quarter 1\\Programming\\Week 1\\PlayerClass\\PlayerClass\\PlayerClass.h"


Player::Player()
{
    name = "";
    health = 100;
    strength = 30;
    stamina = 100;
    experience = 20;
    passive = false;
}

string Player::GetName()
{
    return name;
}

string Player::SetName(string tName)
{
    name = tName;
    return "Ok";
}

int Player::GetHealth()
{
    return health;
}

int Player::SetHealth(int tHealth)
{
    health = tHealth;
}

int Player::GetStrength()
{
    return strength;
}

int Player::SetStrength(int tStrength)
{
    strength = tStrength;
}

int Player::GetStamina()
{
    return stamina;
}

int Player::SetStamina(int tStamina)
{
    stamina = tStamina;
}

int Player::GetExperience()
{
    return experience;
}

int Player::SetExperience(int tExperience)
{
    experience = tExperience;
}

bool Player::GetPassive()
{
    return passive;
}

bool Player::SetPassive(bool tPassive)
{
    passive = tPassive;
}
#include <iostream>
#include <iostream>
#include <dos.h>
#include <string>
#include <sstream>
#include "C:\\Users\\Ryan Bell\\Desktop\\School\\2nd Year\\Quarter 1\\Programming\\Week 1\\PlayerClass\\PlayerClass\\PlayerClass.h"

int main()
{
    Player Player1;
    Player1.SetName("Jake");
    Player1.SetHealth(100);
    Player1.SetStrength(30);
    Player1.SetStamina(50);
    Player1.SetExperience(0);
    Player1.SetPassive(true);

    cout << "Player " << Player1.GetName() << ".";
}

Thank you for your time and help!

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 4
    You will have to add the exact text of the error message. Most of us don't memorize Microsoft error codes especially ones using a different compiler. Its best to get the text from the Output Tab of Visual Studio and not the errors list. – drescherjm Jul 27 '21 at 22:12
  • 1
    You did not declare the constructor for your `Player` class in your header but you implemented it in your cpp file. – drescherjm Jul 27 '21 at 22:15
  • 3
    *error C2600: 'Player::Player': cannot define a compiler-generated special member function (must be declared in the class first)* You need a *declaration* of your default constructor in the `Player` class - Just add a line like `Player();` after the `public:` line. But then you will get a number of other errors that your `SetXXX` functions aren't returning a value: either redeclare those as `void` or add `return ;` statements to them. – Adrian Mole Jul 27 '21 at 22:15
  • Adding Player() got rid of the main error, however when I add `return ;`, I still have errors. – Ryan Bell Jul 27 '21 at 22:26
  • 2
    `using namespace std;` is generally a terrible thing, but much worse when used in a header file. [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – Retired Ninja Jul 27 '21 at 22:29
  • 1
    You probably want to make all the Set functions `void` functions instead of declaring them to return a value. You will have to make the change in the header and the cpp file. – drescherjm Jul 27 '21 at 22:29
  • In place of the `` you will need actual variable names or values. – Adrian Mole Jul 27 '21 at 22:29
  • drescherjm, adding doing that I am left with the error unresolved external symbol – Ryan Bell Jul 27 '21 at 22:31
  • 1
    ***I am left with the error unresolved external symbol*** That means you did not implement whatever function that the linker is complaining about. Remember that the function signature must be an exact match from your declaration in the header and the function you implemented in the cpp file. – drescherjm Jul 27 '21 at 22:33
  • Adrian I did replace – Ryan Bell Jul 27 '21 at 22:33
  • With an error number like 2600 I'm tempted to recommend [checking your modem](https://en.wikipedia.org/wiki/2600_hertz). – user4581301 Jul 27 '21 at 22:54

2 Answers2

1

I don't see a Player Constructor declared:

// I see the Player Constructor definition here.
Player::Player()
{
    .....

But this method is not declared in the class.

class Player
{
    private:
    .....
    public:
        Player();           // Add this line.
        string GetName();

PS. Your code should compile and "probably" runs but is not good. If you can show it working, you can take it to Code Review and get them to give you advice on how to make it better (and some obvious errors corrected).

Martin York
  • 257,169
  • 86
  • 333
  • 562
1

The compilation of your code gives:

2.cpp: In member function ‘int Player::SetStamina(int)’:
2.cpp:18:1: warning: no return statement in function returning non-void [-Wreturn-type]
   18 | }
      | ^
2.cpp: In member function ‘int Player::SetExperience(int)’:
2.cpp:28:1: warning: no return statement in function returning non-void [-Wreturn-type]
   28 | }
      | ^
2.cpp: In member function ‘bool Player::SetPassive(bool)’:
2.cpp:38:1: warning: no return statement in function returning non-void [-Wreturn-type]
   38 | }

These can be fixed by turning all setters as functions returning void, e.g:

void Player::SetStamina(int tStamina)

Do it both in *.h and player.cpp.

After fixing this, we bump onto linker errors:

/usr/bin/ld: /tmp/ccQk0cvm.o: in function `main':
main.cpp:(.text+0x6c): undefined reference to `Player::SetName(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
/usr/bin/ld: main.cpp:(.text+0xa7): undefined reference to `Player::SetHealth(int)'
/usr/bin/ld: main.cpp:(.text+0xb8): undefined reference to `Player::SetStrength(int)'
/usr/bin/ld: main.cpp:(.text+0x11a): undefined reference to `Player::GetName[abi:cxx11]()'
collect2: error: ld returned 1 exit status

This means that you forgot to define Player::GetName, Player::SetStrength(int), and 2 other methods.

This leads us to the simplest solution (for now): modify the public section of your class so that it implements all functions:

    public:
        std::string GetName() const { return name; }
        void SetName(string tName) { name = tName; }
        int GetHealth() const { return health; }
        void SetHealth(int tHealth) { health = tHealth; }
        int GetStrength() const { return strength; }
        void SetStrength(int tStrength) { strength = tStrength; }
        int GetStamina() const { return stamina; }
        void SetStamina(int tStamina) { stamina = tStamina; }
        int GetExperience() const { return experience; }
        void SetExperience(int tExperience) { experience = tExperience; }
        bool GetPassive() const { return passive; }
        void SetPassive(bool tPassive) { passive = tPassive; }

and don't use a separate source file for the class member definitions.

Alternatively, you can keep the file, but then you must add all missing function definitions in it.

Notice that I declared all getters as const member functions. Believe me, this is how they should be defined.

zkoza
  • 2,644
  • 3
  • 16
  • 24
  • 3
    Side note: Prefer methods that operate on the object and return a result to exposing setters and getters that users can call to get value's, perform computations outside of the object, and then set the results back into the object. It allows the object to better defend itself against misuse and bugs and generally makes maintaining debugging easier as manipulation of the object isn't splattered all over the codebase. In terms of encapsulation, a `public` setter with no protections or value add is only a little better than a `public` variable. – user4581301 Jul 27 '21 at 23:12