友元成员函数的注意事项
友元的概念
“友元”的概念其实是针对于类的私有成员来说的,一个类的由于封装的缘故,类体中私有成员是不可以被外界访问的,无论是继承也好,都是无法访问类内私有成员的。但是正是有那么一些人,愿意打破陈规破例访问类体内的私有成员,此时“友元”的概念闪亮登场。其实我们的普通函数是可以访问类体中的public,但是自从来了“友元”,protected和private类型的变量都被尽收眼底,无处可藏。
友元成员函数中的注意事项
友元成员函数声明和定义的顺序必须满足一定要求,否则VS2017会报错。
#include <iostream>
#include <string>
using namespace std;
class Person;
class Student
{
public:
void ShowInf(Person& PersonObject);
};
class Person
{
friend void Student::ShowInf(Person& PersonObject);
private:
int age;
string name;
public:
Person(string name, int age)
{
this->name = name;
this->age = age;
}
Person(Person& PersonObject)
{
this->name = PersonObject.name;
this->age = PersonObject.age;
}
Person operator = (Person PersonObject)
{
this->age = PersonObject.age;
this->name = PersonObject.name;
}
};
void Student::ShowInf(Person& PersonObject)
{
cout << PersonObject.name << "的年龄为" << PersonObject.age << endl;
}
int main()
{
Person PersonObject("张三", 19);
Student StudentObject;
StudentObject.ShowInf(PersonObject);
}
我们这里用Student类中的ShowInf()成员函数访问Person类中的私有成员name和age。
① 首先,我们先声明可以下Person类类型,这样我们才可以在下面定义Student类使用这个数据类型,但是一定要注意,此时的Person类是个空类只是个声明我任何实际成员参数,因此我们Student中的ShowInf()要在Person类定义完后在进行定义,此时我们才可以在Student中的ShowInf()中访问Person类中的成员,这里我们先给Student中的ShowInf()函数一个类内声明;
② 定义Person类的实体,在定义Person类实体之前,千万不要定义Student中的ShowInf()函数,因为Person类实体未定义之前我们也不知道Person类中有什么成员;
③ 定义Student类中可以访问呢Person类私有成员的函数实体,此时定义实体才有意义,编译器才不会报错,因为,这个时候Person类内有啥已经知道了,访问Person类中的成员也就顺理成章了。
④ 特别注意:这里我们只能通过向函数传递形参来访问Person类中的私有成员,因为在Person实体未定义之前,编译器是不允许我们定义Person类的对象的。
错误示例
#include <iostream>
#include <string>
using namespace std;
class Person;
class Student
{
private:
Person PersonObject;
public:
void ShowInf();
Student(Person PersonObject)
{
this->PersonObject = PersonObject;
}
};
class Person
{
friend void Student::ShowInf();
private:
int age;
string name;
public:
Person(string name, int age)
{
this->name = name;
this->age = age;
}
Person(Person& PersonObject)
{
this->name = PersonObject.name;
this->age = PersonObject.age;
}
Person operator = (Person PersonObject)
{
this->age = PersonObject.age;
this->name = PersonObject.name;
}
};
void Student::ShowInf()
{
cout << PersonObject.name << "的年龄为" << PersonObject.age << endl;
}
int main()
{
Person PersonObject("张三", 19);
Student StudentObject(PersonObject);
StudentObject.ShowInf();
}
这里,我们在未定义Person实体之前(仅仅定义了一个Person类的声明)就在Student类体内定义Person类的成员函数,这样的话编译器并不知道给Person类对象分配多少内存空间,因此此时编译器会报错!
我们一定要注意:在未定义的类实体之前,一定不要贸然的在其他类体内定义该类类型的对象作为成员变量。