i started learning about operators overloading, at first it seem to easy, but now am having a problem accessing private member when try to make a global funtion operator
player.hpp
#ifndef _PLAYER_HPP_
#define _PLAYER_HPP_
#include <iostream>
#include <string>
#include "item.h"
class player
{
friend player operator+(player& obj, player& tem);
static int numPlayer;
float *health;
int mspeed;
int damage;
int xp;
std::string name;
public:
// Constructors
player(std::string = "player", float _health = 100, int _xp = 0);
// Copy Constructor
player(const player& obj);
// Move Constructor
player(player&& obj);
// Functions
void display();
// Friends functions
friend void test(player user);
friend player operator+(player &&obj, const item &tem);
// Diconstructors
~player();
};
#endif // _PLAYER_HPP_
player.cpp
#include "player.hpp"
#include "item.h"
#include <iostream>
#include <cstring>
#include <string>
int player::numPlayer = 0;
// Constructors
player::player(std::string _name, float _health, int _xp) {
numPlayer++;
this->health = new float;
*this->health = _health;
this->xp = _xp;
this->name = _name;
std::cout << "constructor for " << this->name << std::endl;
}
// Copy constructors
player::player(const player& obj) {
this->health = new float;
*this->health = *obj.health;
this->xp = obj.xp;
this->name = obj.name;
std::cout << "copy constructor for " << this->name << std::endl;
}
// Move Constructors
player::player(player&& obj) {
this->damage = 60;
this->mspeed = 50;
this->health = obj.health;
this->xp = obj.xp;
this->name = obj.name;
obj.health = nullptr;
std::cout << "Move constructor for " << this->name << std::endl;
}
void player::display() {
std::cout << "========================" << std::endl
<< this->name << std::endl
<< *this->health << std::endl
<< this->xp << std::endl
<< this->damage << std::endl
<< this->mspeed << std::endl;
}
player::~player() {
delete[] health;
std::cout << "distruction for: " << name << std::endl;
}
void test(player user) {
std::cout << user.name << std::endl;
}
player operator+(player&& obj, const item& tem) {
*obj.health += tem.health;
obj.damage += tem.damage;
obj.mspeed += tem.ms;
return obj;
}
item.h
#ifndef _ITEM_H_
#define _ITEM_H_
#include <iostream>
#include <string>
#include "player.hpp"
class item {
int damage; // Bonus damage
int health; // Bonus health
int ms; // Bonus Movement speed
std::string name; // item name
public:
//constructor
item(std::string name, int _damage = 0, int _health = 0, int _ms = 0)
: name {name}, damage {_damage}, health{_health}, ms {_ms}{}
friend player operator+(player &&obj,const item &tem);
};
#endif // _ITEM_
Main.cpp
#include <iostream>
#include <string>
#include "player.hpp"
#include "item.h"
player operator+(player&& obj, const item& tem);
void test(player user);
void main(int args, char* argv) {
player a("YASOU96");
item deathSword("death Sword", 150, 0, 20);
a.display();
a = a + deathSword;
a.display();
}
i dont see that there is a mistake there but it keep showing on visual studio item class member are private (can't access em), nd if i switch between the player.hpp and item.h header order, i can have access to item private member, nd then i lose access on player.hpp private member
Any help would be appreciated.
First things first, Error #1:
main.cpp:9:1: error: ‘::main’ must return ‘int’
9 | void main(int args, char* argv) {
| ^~~~
main.cpp:9:6: warning: second argument of ‘int main(int, char*)’ should be ‘char **’ [-Wmain]
9 | void main(int args, char* argv) {
| ^~~~
The fix is easy:
int main(int args, char* argv[])
or
int main([[maybe_unused]] int args, [[maybe_unused]] char* argv[])
or even
int main()
Error #2:
In file included from player.hpp:6,
from main.cpp:3:
item.h:18:12: error: ‘player’ does not name a type
18 | friend player operator+(player &&obj,const item &tem);
| ^~~~~~
This is more difficult to interpret. Your class item
depends on class player
and player
depends on item
. This is impossible for the compiler to go through. Solution:
In item.h
replace
#include "player.hpp"
with
class player;
This is a forward declaration. Class item
uses player
only here:
friend player operator+(player &&obj,const item &tem);
that is, the compiler needs to form only a reference to a player
, it needs not to have the detailed knowledge about what player
actually is. This is a common "trick": when class A uses only pointers or references to B, the forward declaration of B is completely enough. Moreover, be eliminating #include
, you speed up the compilation a bit.
main.cpp: In function ‘int main(int, char*)’:
main.cpp:13:9: error: cannot bind rvalue reference of type ‘player&&’ to lvalue of type ‘player’
13 | a = a + deathSword;
| ^
Don't use things you don't understand. Or better: don't use two things you don't understand at the same time. Move semantics is rarely seen outside move constructors. Until you're an expert, try and refrain from using && in places other than the move constructor and moving operator=
. Actually, even if you won't use them at all, your program will be perfectly correct - not using move semantics does not make the program incorrect, it may only render it run a bit slower that it could with move semantics being used correctly. So, turn:
friend player operator+(player &&obj,const item &tem);
into
friend player operator+(player &obj, const item &tem);
Also, delete the move constructor in player
and any cases where you use &&
, because it moves nothing. All you do is to shoot at your knee.
Error #4
After all these changes, the compiler presents a series of new complaints of similar type:
player.cpp: In function ‘player operator+(player&&, const item&)’:
player.cpp:58:24: error: ‘int item::health’ is private within this context
58 | *obj.health += tem.health;
| ^~~~~~
In file included from player.hpp:6,
from player.cpp:1:
item.h:11:9: note: declared private here
11 | int health; // Bonus health
This is because you messed up almost all friend declaration(s). The fix is similar to the one used in `item.hpp". Instead of
friend player operator+(player& obj,const player& tem);
declare
class item;
and then the true operator+:
friend player operator+(player& obj, const item& tem);
Error 5
Remove * from *obj.health += tem.health;
GENERAL REMARKS
and I didn't even look into the quality of your code, I just tried to made it compile.