Example of C++ middle friend
- 2020-05-27 06:47:51
- OfStack
Example of C++ middle friend
Although friends are granted external access to private parts of a class, they do not contradict object-oriented programming ideas; Instead, he increased the flexibility of public interfaces.
1. The metaclass
The youyuan declaration can be in the public or private protected parts, and its location does not matter
I'm just going to post an excerpt
<
c++ primer plus
>
c++ friend class
Where Remote is the friend class of Tv.
Tv.h
#ifndef TV_H_
#define TV_H_
/*1 A class TV */
class Tv
{
public:
friend class Remote; //Remote Class can be accessed Tv Privite Private part
enum {
off,on // switch
};
enum
{
MinVal,MaxVal=20 // The volume
};
enum {
Antena,Cable // Using an antenna or a cable
};
enum
{
TV ,DVD // Working mode
};
Tv(int s = off, int mc = 125) :state(s), volume(5), maxchannel(mc),
channel(5), mode(Cable), input(TV) {}
void onoff() { state = (state == on) ? off : on; }
bool ison()const { return state == on; }
bool volup(); // Increase the voice
bool voldown(); // Reduce the sound
void chanup(); // channel +
void chandown();// channel -
void set_mode() { mode = (mode == Antena) ? Cable : Antena; }
void set_input() { input = (input == TV) ? DVD : TV; }
void settings()const; // Display all Settings
private:
int state; // Open or guan
int volume; // The volume
int maxchannel; // The biggest
int channel; // The current channel
int mode; // Radio or cable
int input; //Tv or DVD
};
/*Remote The definition of (remote control) */
class Remote {
private :
int mode; // control TV or DVD
public:
Remote(int m = Tv::TV) :mode(m) {}
bool volup(Tv & t) { return t.volup(); }
bool voldown(Tv & t) { return t.voldown(); }
void onoff(Tv & t) { return t.onoff(); }
void chanup(Tv & t) { return t.chanup(); }
void chandown(Tv & t) { return t.chandown(); }
void set_chan(Tv &t, int c) { t.channel = c; } // Access to the Tv Private member of
void set_mode(Tv &t) { t.set_mode(); }
void set_input(Tv &t) { t.set_input(); }
};
#endif // TV_H_
Tv.cpp
#include "stdafx.h"
#include "Tv.h"
#include <iostream>
bool Tv::volup() {
if (volume < MaxVal) {
volume++;
return true;
}
else {
return false;
}
}
bool Tv::voldown() {
if (volume > MinVal) {
volume--;
return true;
}
else {
return false;
}
}
void Tv::chanup() {
if (channel < maxchannel) channel++;
else channel = 1;
}
void Tv::chandown() {
if (channel > 1) channel--;
else channel = maxchannel;
}
void Tv::settings() const {
using std::cout;
using std::endl;
cout << "TV is " << (state == off ? "off" : "on") << endl;
if (state == on) {
cout << "Volume setting =" << volume << endl;
cout << "Channel setting = " << channel << endl;
cout << "Mode = " << (mode == Antena ? "antenna" : "cable") << endl;
cout << "Input = " << (input == TV ? "TV" : "DVD") << endl;
}
}
Test code:
#include "stdafx.h"
#include "tv.h"
#include <iostream>
int main()
{
using std::cout;
Tv s42;
cout << "Initial settings for 42 \" Tv: \n";
s42.settings();
s42.onoff();
s42.chanup();
cout << " \n Adjusted settings for 42 \" Tv: \n";
s42.chanup();
cout << "\n Adjusted settings for 42 \" Tv: \n";
s42.settings();
Remote grey;
grey.set_chan(s42, 10);
grey.volup(s42);
grey.volup(s42);
cout << " \n s42 \" settings after using remote: \n";
s42.settings();
Tv s58(Tv::on);
s58.set_mode();
grey.set_chan(s58, 58);
cout << " \n s58 \" setting: \n";
s58.settings();
system("pause");
return 0;
}
Operation results:
Initial settings for 42 " Tv:
TV is off
Adjusted settings for 42 " Tv:
Adjusted settings for 42 " Tv:
TV is on
Volume setting =5
Channel setting = 7
Mode = cable
Input = TV
s42 " settings after using remote:
TV is on
Volume setting =7
Channel setting = 10
Mode = cable
Input = TV
s58 " setting:
TV is on
Volume setting =5
Channel setting = 58
Mode = antenna
Input = TV
Please press any key to continue . . .
The code above sets the Remote class to be a friend of the Tv class, but in fact we can see that the only way a member of Tv can be accessed is by void set_chan(Tv) & t, int c) {t.channel = c; }, so it is the only method that needs a friend. So you don't have to make the whole class a friend, which leads to the friend member function that we're going to talk about next.
2. Friend member function
In Tv, we will set Remote::set_chan() as friendly element:
clas Tv
{
friend void Remote::set_chan(Tv & t,int c ) ;
}
However, for the compiler to be able to process this statement, it must know the definition of Remote. Otherwise, it cannot know that Remote is a class. set_chan is a method of this class. This means that the definition of Remote should precede the definition of Tv. The Remote method refers to the Tv object, which means that the Tv definition should precede the Remote definition. The way around this loop dependency is to use forward declarations.
So it should look like this:
class Tv ; // Prior to declaration
class Remote{...}
class Tv {...}
Here's another problem:
Remote contains inline code such as void onoff(Tv)
&
t) {t.onoff();};
Since this calls one of Tv's methods, the compiler will have seen the Tv class declaration at this point so it knows what Tv's methods are, but as you can see, this declaration follows the Remote declaration. The solution to this problem is to use the Remote declaration to include only method declarations, and put the actual definition behind the Tv class. So it should end up like this:
class Tv; // Prior to declaration
class Remote {...} // If you want to use Tv Only method declarations
class Tv{...}
// Then write Remote The definition of
You can still call a method inline by using the inline keyword in the method definition
So the program eventually changed tv.h to:
#ifndef TV_H_
#define TV_H_
class Tv; // Prior to declaration
class Remote {
public:
enum {
off, on // switch
};
enum
{
MinVal, MaxVal = 20 // The volume
};
enum {
Antena, Cable // Using an antenna or a cable
};
enum
{
TV, DVD // Working mode
};
private:
int mode; // control TV or DVD
public:
Remote(int m = TV) :mode(m) {}
// With the help of Tv Only statements
bool volup(Tv & t);
bool voldown(Tv & t);
void onoff(Tv & t);
void chanup(Tv & t);
void chandown(Tv & t);
void set_chan(Tv &t, int c);
void set_mode(Tv &t);
void set_input(Tv &t);
};
class Tv
{
public:
friend void Remote::set_chan(Tv & t,int c); // Friend member function
enum {
off, on // switch
};
enum
{
MinVal, MaxVal = 20 // The volume
};
enum {
Antena, Cable // Using an antenna or a cable
};
enum
{
TV, DVD // Working mode
};
Tv(int s = off, int mc = 125) :state(s), volume(5), maxchannel(mc),
channel(5), mode(Cable), input(TV) {}
void onoff() { state = (state == on) ? off : on; }
bool ison()const { return state == on; }
bool volup(); // Increase the voice
bool voldown(); // Reduce the sound
void chanup(); // channel +
void chandown();// channel -
void set_mode() { mode = (mode == Antena) ? Cable : Antena; }
void set_input() { input = (input == TV) ? DVD : TV; }
void settings()const; // Display all Settings
private:
int state; // Open or guan
int volume; // The volume
int maxchannel; // The biggest
int channel; // The current channel
int mode; // Radio or cable
int input; //Tv or DVD
};
inline bool Remote::volup(Tv & t) { return t.volup(); }
inline bool Remote::voldown(Tv & t) { return t.voldown(); }
inline void Remote::onoff(Tv & t) { return t.onoff(); }
inline void Remote::chanup(Tv & t) { return t.chanup(); }
inline void Remote::chandown(Tv & t) { return t.chandown(); }
inline void Remote::set_chan(Tv &t, int c) { t.channel = c; }
inline void Remote::set_mode(Tv &t) { return t.set_mode(); }
inline void Remote::set_input(Tv &t) { return t.set_input(); }
#endif // TV_H_
The test results remain the same.
* also: you can put an inline function in tv.cpp, but you must remove the inline keyword so that the connectivity of the function becomes external.
3. Other friend relationships
1. The above code indicates that Remote is a friend of Tv. But we also sometimes use two classes that are friends with each other. So Remote is the friend of Tv, and Tv is the friend of Remote
Their definition is similar to the following:
class Remote
class Tv
{
friend clas Remote
public:
void buzz(Remote & r) ;
...
}
class Remote
{
friend class Tv;
public:
void Bool volup(Tv & t){t.volup();}
...
}
inline void Tv::buzz(Remote & r)
{
...
}
Since Remote's declaration follows the Tv declaration, it is possible to define Remote::volup() in the class's definition, but the Tv::buzz() method must be defined outside the Tv declaration so that it is outside the Remote declaration. If you do not want buzz() to be inline, you should define it in a separate method definition file.
2. Mutual friends.
Another situation where you need to use a friend is when a function needs to access private data from two classes. It can be a friend of one class and a friend of another class. Here's an example:
class Analyzer;
class Probe
{
friend void sync (Analyzer & a,const Probe & p) ;
friend void sync (Probe & p,const Analyzer & a);
...
};
class Analyzer
{
friend void sync (Analyzer & a,const Probe & p) ;
friend void sync (Probe & p,const Analyzer & a);
}
inline void sync (Analyzer & a,const Probe & p)
{
...
}
inline void sync (Probe & p,const Analyzer & a)
{
...
}
If you have any questions, please leave a message or come to the site community to exchange discussion, thank you for reading, hope to help you, thank you for your support of the site!