简体   繁体   English

朋友 function 无法访问私人会员

[英]friend function cant access private memebers

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播放器.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播放器.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项目.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我没有看到那里有错误,但它一直显示在 Visual Studio 项目 class 成员是私有的(无法访问 em),如果我在 player.hpp 和 item.h header 订单之间切换,我可以访问项目私人会员,然后我失去了对 player.hpp 私人会员的访问权限

Any help would be appreciated.任何帮助,将不胜感激。

First things first, Error #1:首先,错误#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:错误 #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 .您的 class item取决于 class playerplayer取决于item This is impossible for the compiler to go through.这对于编译器来说是不可能通过 go 的。 Solution:解决方案:

In item.h replaceitem.h替换

#include "player.hpp"

with

class player;

This is a forward declaration.这是一个前向声明。 Class item uses player only here: Class item仅在此处使用player

    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.也就是说,编译器只需要形成对player的引用,它不需要知道player到底是什么。 This is a common "trick": when class A uses only pointers or references to B, the forward declaration of B is completely enough.这是一个常见的“技巧”:当 class A 仅使用指向 B 的指针或引用时,B 的前向声明完全足够了。 Moreover, be eliminating #include , you speed up the compilation a bit.此外,消除#include可以加快编译速度。

  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= .在您成为专家之前,请尽量避免在移动构造函数和移动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.此外,删除player中的移动构造函数以及使用&&任何情况,因为它什么也不移动。 All you do is to shoot at your knee.你所做的就是向你的膝盖射击。

Error #4错误 #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该修复类似于“item.hpp”中使用的修复。而不是

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;错误 5*obj.health += tem.health;

GENERAL REMARKS一般说明

  • Don't write tons of code without compiling it.不要在不编译的情况下编写大量代码。 If you're learning a new language / how to program, write a few lines and compile.如果您正在学习一门新语言/如何编程,请编写几行代码并编译。 In this way you'll always face 1, perhaps two bugs, usually easy to localize.这样,您将始终面临 1 个,也许是两个错误,通常很容易本地化。
  • Don't learn several things at a time.不要一次学习几样东西。 Here you've shown you have a very limited understanding of:在这里,您表明您对以下内容的理解非常有限:
    • how to handle multiple source / header files,如何处理多源/header 文件,
    • what is move semantics,什么是移动语义,
    • how to use friend declarations.如何使用朋友声明。

and I didn't even look into the quality of your code, I just tried to made it compile.我什至没有调查你的代码质量,我只是试图让它编译。

  • If you're C++ beginner, you don't need move semantics, friend declaration, operator overloading.如果你是 C++ 初学者,你不需要移动语义、友元声明、运算符重载。 Trying to use these features, you're distracting your attention from really important objectives.尝试使用这些功能时,您会将注意力从真正重要的目标上转移开。 You don't have to be a C++ expert to use it.您无需成为 C++ 专家即可使用它。 Learn gradually and use only the tools you understand well, or learn one thing at a time.循序渐进地学习,只使用你熟悉的工具,或者一次学习一件事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM