-2

I study C ++, I am also not strong in it, so do not judge strictly, played with classes, and decided to make 2 classes so that you can try their prototypes, to which I received in response, in the 1st case, not a complete description of the class, and in the second There is no access to the fields and in general to class. I watched the lesson on the OOP, and there the person worked this code, I decided to try myself what I was surprised, and I don't even know what to do who can explain why and how, I will be happy to hear. thanks in advance.

class human;

class apple {
   private:
    int weight;
    string color;

   public:
    apple(const int weight, const string color) {
        this->weight = weight;
        this->color = color;
    }

    friend void human::take_apple(apple& app);
};

class human {
   public:
       void take_apple(apple& app) {};
};

Error: Incomplete type 'human' named in nested name specifer.

class apple;

class human {
   public:
       void take_apple(apple& app) {
           cout << app.color << '\n';
       };
};

class apple {
   private:
    int weight;
    string color;

   public:
    apple(const int weight, const string color) {
        this->weight = weight;
        this->color = color;
    }

    friend void human::take_apple(apple& app);
};

Error: Member access into incomplete type 'apple'.

  • Use the second approach, but move the implementation of `human::take_apple` to the end of the snippet: `... class human {public: void take_apple(apple& app);}; class apple{...}; inline void human::take_apple(apple& app) { cout << app.color << '\n'; }` – fabian Apr 15 '22 at 16:00
  • @drescherjm Yes, I understand what you can do through Header, but I am interested in a clean situation, it's just my interest Why is it possible to fix it. – Danil Danevich Apr 15 '22 at 16:00
  • I think I was totally confused at what you are trying to do. – drescherjm Apr 15 '22 at 16:02
  • @drescherjm I just want to understand why there is such a mistake, and how to fix them remain in the same main.cpp file – Danil Danevich Apr 15 '22 at 16:04
  • @DanilDanevich Did you keep the forward declaration of `apple`? My compiler doesn't complain about the snippet I suggested at all... – fabian Apr 15 '22 at 16:16
  • A note on terminology: This is called a _forward declaration_. A _prototype_ is a specific form of function declaration in C which has no relevant distinction in C++. – user17732522 Apr 15 '22 at 16:25

1 Answers1

2

Before befriending a member function, there must be a declaration for that member function in the respective class(which is human in this case).

To solve this you can declare the member function before and the define it afterward the class apple's definition as shown below:

class apple; //friend declaration for apple
class human {
   public:
       void take_apple(apple& app);//this is a declaration for the member function
};

class apple {
   private:
    int weight;
    std::string color;

   public:
    apple(const int weight, const std::string color) {
        this->weight = weight;
        this->color = color;
    }

    friend void human::take_apple(apple& app);
};
//this is the definition of the member function
void human::take_apple(apple& app) {};

Working demo

Note: In case you want to put the implementation of member function take_apple inside a header file make sure that you use the keyword inline.

Jason
  • 36,170
  • 5
  • 26
  • 60
  • 1
    It should be noted that putting this snippet in a header file used in multiple translation units linked together won't work, since this would produce multiple definitions of `human::take_apple`. To fix this the function should be made `inline` in that scenario. – fabian Apr 15 '22 at 16:06
  • Notice you have to define the whole `human` class here, which may be precisely what OP was trying to avoid. – Spencer Apr 15 '22 at 16:08
  • @fabian Yes, but no such requirement was given by the OP. I have added a note at the end of my answer saying that `inline` should be used in case the implementation of the member function is inside the header file. – Jason Apr 15 '22 at 16:09
  • In case you were addressing me with that first sentence, `not a complete description of the class` seems like the statement of such a requirement to me. – Spencer Apr 15 '22 at 16:12
  • Thx! Work) What about first code? – Danil Danevich Apr 15 '22 at 16:14
  • 1
    @DanilDanevich The 1st snippet doesn't work because befriending a member function requires a declaration for that member function inside the respective class(which is `human` in your case). While the 2nd snippet doesn't work because the expression `apple.color` requires the definition of class `apple`. – Jason Apr 15 '22 at 16:22
  • @AnoopRana No solutions, right? In terms of a particular bike. – Danil Danevich Apr 15 '22 at 16:23
  • @DanilDanevich The solution is the same that i gave in my answer for both of the snippets. I would also recommend learning C++ using some [good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). In particular, C++ Primer by Lippman is a beginner friendly recommendation. – Jason Apr 15 '22 at 16:24
  • And for the book) – Danil Danevich Apr 15 '22 at 16:27