C++中friend的使用

C++中friend的使用友元函数并不能看做是类的成员函数,它只是个被声明为类友元的普通函数:(1)、在类里声明一个普通函数,在前面加上friend修饰,那么这个函数就成了该类的友元,可以访问该类的一切成员

友元函数并不能看做是类的成员函数,它只是个被声明为类友元的普通函数:

(1)、在类里声明一个普通函数,在前面加上friend修饰,那么这个函数就成了该类的友元,可以访问该类的一切成员。

(2)、一个普通函数可以是多个类的友元函数。

(3)、一个类的成员函数也可以是另一个类的友元,从而可以使得一个类的成员函数可以操作另一个类的数据成员。

(4)、整个类也可以是另一个类的友元,该友元也可以称作为友类。友类的每个成员函数都可以访问另一个类的所有成员。

友元声明中声明的函数被视为已使用extern关键字声明。

friend函数是一个不是类成员的函数,但它可以访问类的私有和受保护的成员。友元函数不被视为类成员,它们是获得了特殊访问权限的普通外部函数。友元不在类的范围内除非它们是另一个类的成员,否则不能使用成员选择运算符(.和->)调用它们。friend函数由授予访问权限的类声明。可将friend声明放置在类声明中的任何位置。它不受访问控制关键字的影响。

友元关系不是相互的,除非显示指定。友元关系不能继承。友元关系不可传递。

类的外部,也就是通过实例来访问私有(private)或保护(protected)成员,这是被禁止的。但从实用性来说,的确有时很需要在外部访问,C++增加了一种称之为“友元(friend)”函数的声明,将“特权”赋给一些函数(可以是全局函数,也可以是其它类的成员函数),使之能够访问该类的私有和保护成员。

友元函数必须在类里面声明,而且友元函数一定不是该类的成员函数。另外,友元函数的声明在派生类无效,除非派生类中再声明一次,当然类型转换为基类时,使用没有任何问题。

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "friend.hpp"
 
#include <sstream>
#include <iostream>
 
// reference: https://msdn.microsoft.com/zh-cn/library/465sdshe.aspx
class Point_ {
	friend void ChangePrivate(Point_ &);
public:
	Point_(void) : m_i(0) {}
	void PrintPrivate(void){ std::cout << m_i << std::endl; }
 
private:
	int m_i;
};
 
// friend 函数可以访问其接受为参数的 Point_ 对象的私有数据成员
void ChangePrivate(Point_ &i)
{
	i.m_i++;
}
 
int test_friend1()
{
	Point_ sPoint;
	sPoint.PrintPrivate(); // 0
	ChangePrivate(sPoint);
	sPoint.PrintPrivate(); // 1
 
	return 0;
}
 
 
class B_f;
 
class A_f {
public:
	int Func1(B_f& b);
private:
	int Func2(B_f& b);
};
 
class B_f {
private:
	int _b;
 
	// A::Func1 is a friend function to class B
	// so A::Func1 has access to all members of B
	// 类成员函数可以声明为其他类中的友元
	friend int A_f::Func1(B_f&);
};
 
int A_f::Func1(B_f& b) { return b._b; }   // OK
//int A_f::Func2(Bf_& b) { return b._b; }   // C2248
 
///
class YourClass {
	// friend 类是其所有成员函数都是类的友元函数的类,即,其成员函数具有对类的私有成员和受保护成员访问权限.
	// 友元关系不是相互的,除非显式指定。YourClass 的成员函数无法访问 YourOtherClass 的私有成员.
	// 友元关系不能继承,这意味着从 YourOtherClass 派生的类不能访问 YourClass 的私有成员.
	// 友元关系不可传递,因此 YourOtherClass 的友元类无法访问 YourClass 的私有成员。
	friend class YourOtherClass;  // Declare a friend class
public:
	YourClass() : topSecret(0){}
	void printMember() { std::cout << topSecret << std::endl; }
private:
	int topSecret;
};
 
class YourOtherClass {
public:
	void change(YourClass& yc, int x){ yc.topSecret = x; }
};
 
int test_friend2()
{
	YourClass yc1;
	YourOtherClass yoc1;
	yc1.printMember(); // 0
	yoc1.change(yc1, 5);
	yc1.printMember(); // 5
 
	return 0;
}
 
///
// reference: http://en.cppreference.com/w/cpp/language/friend
template<typename T>
class Foo {
public:
	Foo(const T& val) : data(val) {}
private:
	T data;
 
	// generates a non-template operator<< for this T
	friend std::ostream& operator<<(std::ostream& os, const Foo& obj)
	{
		return os << obj.data;
	}
};
 
int test_friend3()
{
	Foo<double> obj(1.23);
	std::cout << obj << '\n'; // 1.23
 
	return 0;
}
 
///
template<typename T>
class Foo_; // forward declare to make function declaration possible
 
template<typename T> // declaration
std::ostream& operator<<(std::ostream&, const Foo_<T>&);
 
template<typename T>
class Foo_ {
public:
	Foo_(const T& val) : data(val) {}
private:
	T data;
 
	// refers to a full specialization for this particular T 
	friend std::ostream& operator<< <> (std::ostream&, const Foo_&);
	// note: this relies on template argument deduction in declarations
	// can also specify the template argument with operator<< <T>"
};
 
// definition
template<typename T>
std::ostream& operator<<(std::ostream& os, const Foo_<T>& obj)
{
	return os << obj.data;
}
 
int test_friend4()
{
	Foo_<double> obj(1.23);
	std::cout << obj << '\n'; // 1.23
 
	return 0;
}
 
///
class MyClass {
	int i;
 
	friend std::ostream& operator<<(std::ostream& out, const MyClass& o);
	friend std::istream& operator>>(std::istream& in, MyClass& o);
public:
	MyClass(int i = 0) : i(i) {}
};
 
std::ostream& operator<<(std::ostream& out, const MyClass& mc)
{
	return out << mc.i;
}
 
std::istream& operator>>(std::istream& in, MyClass& mc)
{
	return in >> mc.i;
}
 
int test_friend5()
{
	MyClass mc(7);
	std::cout << mc << '\n'; // 7
	std::istringstream("100") >> mc;
	std::cout << mc << '\n'; // 100
 
	return 0;
}
 
///
// reference: http://www.cplusplus.com/doc/tutorial/inheritance/
class Rectangle {
	int width, height;
public:
	Rectangle() {}
	Rectangle(int x, int y) : width(x), height(y) {}
	int area() { return width * height; }
	friend Rectangle duplicate(const Rectangle&);
};
 
Rectangle duplicate(const Rectangle& param)
{
	Rectangle res;
	res.width = param.width * 2;
	res.height = param.height * 2;
	return res;
}
 
int test_friend6()
{
	Rectangle foo;
	Rectangle bar(2, 3);
	foo = duplicate(bar);
	std::cout << foo.area() << '\n'; // 24
 
	return 0;
}
 
 
class Square_;
 
class Rectangle_ {
	int width, height;
public:
	int area()
	{
		return (width * height);
	}
	void convert(Square_ a);
};
 
class Square_ {
	friend class Rectangle_;
private:
	int side;
public:
	Square_(int a) : side(a) {}
};
 
void Rectangle_::convert(Square_ a) {
	width = a.side;
	height = a.side;
}
 
int test_friend7()
{
	Rectangle_ rect;
	Square_ sqr(4);
	rect.convert(sqr);
	std::cout << rect.area(); // 16
 
	return 0;
}
 
///
// reference: http://www.tutorialspoint.com/cplusplus/cpp_friend_functions.htm
class Box
{
	double width;
public:
	friend void printWidth(Box box);
	void setWidth(double wid);
};
 
// Member function definition
void Box::setWidth(double wid)
{
	width = wid;
}
 
// Note: printWidth() is not a member function of any class.
void printWidth(Box box)
{
	/* Because printWidth() is a friend of Box, it can
	directly access any member of this class */
	std::cout << "Width of box : " << box.width << std::endl;
}
 
int test_friend8()
{
	Box box;
 
	// set box width with member function
	box.setWidth(10.0);
 
	// Use friend function to print the wdith.
	printWidth(box); // 10.0
 
	return 0;
}
 
/
// reference: http://www.programiz.com/cpp-programming/friend-function-class
class Distance
{
private:
	int meter;
public:
	Distance() : meter(0){ }
	friend int func(Distance);  //friend function
};
 
int func(Distance d)            //function definition
{
	d.meter = 5;         //accessing private data from non-member function
	return d.meter;
}
 
int test_friend9()
{
	Distance D;
	std::cout << "Distace: " << func(D); // 5
	return 0;
}
 
///
class B;     // forward declaration
 
class A {
private:
	int data;
public:
	A() : data(12){ }
	friend int func(A, B);   //friend function Declaration
};
 
class B {
private:
	int data;
public:
	B() : data(1){ }
	friend int func(A, B);  //friend function Declaration
};
 
int func(A d1, B d2)
/*Function func() is the friend function of both classes A and B. So, the private data of both class can be accessed from this function.*/
{
	return (d1.data + d2.data);
}
 
int test_friend10()
{
	A a;
	B b;
	std::cout << "Data: " << func(a, b); // 13
 
	return 0;
}
 
///
// reference: https://www.codingunit.com/cplusplus-tutorial-friend-function-and-friend-class
//Must be known to TWO before declaration of ONE.
class ONE;
 
class TWO
{
public:
	void print(ONE& x);
};
 
class ONE
{
	int a, b;
	friend void TWO::print(ONE& x);
public:
	ONE() : a(1), b(2) { }
};
 
void TWO::print(ONE& x)
{
	std::cout << "a is " << x.a << std::endl; // a is 1
	std::cout << "b is " << x.b << std::endl; // b is 2
}
 
int test_friend11()
{
	ONE xobj;
	TWO yobj;
	yobj.print(xobj);
 
	return 0;
}
 
//
class MyClass_
{
	// Declare a friend class
	friend class SecondClass;
 
public:
	MyClass_() : Secret(0){}
	void printMember()
	{
		std::cout << Secret << std::endl;
	}
private:
	int Secret;
};
 
class SecondClass
{
public:
	void change(MyClass_& yourclass, int x)
	{
		yourclass.Secret = x;
	}
};
 
int test_friend12()
{
	MyClass_ my_class;
	SecondClass sec_class;
	my_class.printMember(); // 0
	sec_class.change(my_class, 5);
	my_class.printMember(); // 5
 
	return 0;
}
 
///
// reference: http://www.learncpp.com/cpp-tutorial/813-friend-functions-and-classes/
// A function can be a friend of more than one class at the same time.
class Humidity;
 
class Temperature
{
private:
	int m_temp;
public:
	Temperature(int temp = 0) { m_temp = temp; }
 
	void setTemperature(int temp) { m_temp = temp; }
 
	friend void printWeather(const Temperature &temperature, const Humidity &humidity);
};
 
class Humidity
{
private:
	int m_humidity;
public:
	Humidity(int humidity = 0) { m_humidity = humidity; }
 
	void setHumidity(int humidity) { m_humidity = humidity; }
 
	friend void printWeather(const Temperature &temperature, const Humidity &humidity);
};
 
void printWeather(const Temperature &temperature, const Humidity &humidity)
{
	std::cout << "The temperature is " << temperature.m_temp <<      // 12
		" and the humidity is " << humidity.m_humidity << '\n'; // 10
}
 
int test_friend13()
{
	Humidity hum(10);
	Temperature temp(12);
 
	printWeather(temp, hum);
 
	return 0;
}
 
 
class Storage
{
private:
	int m_nValue;
	double m_dValue;
public:
	Storage(int nValue, double dValue)
	{
		m_nValue = nValue;
		m_dValue = dValue;
	}
 
	// Make the Display class a friend of Storage
	friend class Display;
};
 
class Display
{
private:
	bool m_displayIntFirst;
 
public:
	Display(bool displayIntFirst) { m_displayIntFirst = displayIntFirst; }
 
	void displayItem(Storage &storage)
	{
		if (m_displayIntFirst)
			std::cout << storage.m_nValue << " " << storage.m_dValue << '\n';
		else // display double first
			std::cout << storage.m_dValue << " " << storage.m_nValue << '\n';// 6.7 5
	}
};
 
int test_friend14()
{
	Storage storage(5, 6.7);
	Display display(false);
 
	display.displayItem(storage);
 
	return 0;
}
 
/
class Storage_; // forward declaration for class Storage
 
class Display_
{
private:
	bool m_displayIntFirst;
 
public:
	Display_(bool displayIntFirst) { m_displayIntFirst = displayIntFirst; }
 
	void displayItem(Storage_ &storage); // forward declaration above needed for this declaration line
};
 
class Storage_
{
private:
	int m_nValue;
	double m_dValue;
public:
	Storage_(int nValue, double dValue)
	{
		m_nValue = nValue;
		m_dValue = dValue;
	}
 
	// Make the Display class a friend of Storage (requires seeing the full declaration of class Display, as above)
	friend void Display_::displayItem(Storage_& storage);
};
 
// Now we can define Display::displayItem, which needs to have seen the full declaration of class Storage
void Display_::displayItem(Storage_ &storage)
{
	if (m_displayIntFirst)
		std::cout << storage.m_nValue << " " << storage.m_dValue << '\n';
	else // display double first
		std::cout << storage.m_dValue << " " << storage.m_nValue << '\n'; // 6.7 5
}
 
int test_friend15()
{
	Storage_ storage(5, 6.7);
	Display_ display(false);
 
	display.displayItem(storage);
 
	return 0;
}

 

今天的文章C++中friend的使用分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/61421.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注