目录
1.定义:
1.概念:
2.注意
3.友元的分类:
4.友元函数代码分析:
1.友元函数出现的原因(外部函数友元为例):
2.一个外部函数作为多个类的友元函数
3.成员函数友元:
4.类友元:
5.特点:
1.不具有对称性 :
2.不具有传递性 :
3.不具有继承性:
6.总结:
1.友元函数不是类的成员函数。
2.友元函数不受类中的访问权限关键字限制。
3.某类的友元函数的作用域并非该类作用域。
友元 friend 机制允许一个类授权其他的函数访问它的非公有成员。友元声明以关键字 friend 开头 ,它只能出现在类的声明中, 它们不受其在类体中的 public private 和 protected 区的影响.。
通俗来说就是就是让函数或者类作为另外一个类的朋友,则可以访问当前类的private或者protected类。
1.一个普通函数作为类的友元,那么在当前函数中就可以通过对象访问类的私有或者保护成员
注意:这个函数只能在外部定义,在当前类中引用即可
2.一个类的成员函数作为另外一个类的友元
注意:成员函数建议放在类外定义
3.一个类A作为另外一个类B的友元类,则A的所有的成员函数就可以访问B的私有数据成员或者保护
友元分为外部函数友元, 成员函数友元,类友元。
class A
{
public:
A(int i=0):m_i(i){}
private:
int m_i;
};
void main()
{
A a(5);
A b(8);
Add(a, b);
}
想在Add函数中访问私有数据成员,在之前我们通过接口实现了Add函数,那如果不想通过接口(共有函数),我们可以怎么实现呢?
class A
{
public:
A(int i=0):m_i(i){}
int GetI()const
{
return m_i;
}
friend void Add(A& a, A& b);//将Add函数作为类A的友元,在类外部定义,(不能在类A中定义)
protected:
//friend void Add(A& a, A& b);
private:
int m_i;
//friend void Add(A& a, A& b);
};
//想在Add函数中访问私有数据成员,又不想通过接口(公有函数)
void Add(A& a, A& b)
{
cout << a.m_i + b.m_i << endl;
//cout << a.GetI() + b.GetI() << endl;//接口
}
void main()
{
A a(5);
A b(8);
Add(a, b);
}
分析:
1.在类A的外部写入了一个公有函数
2.在类A中写入friend void Add(A& a, A& b);即就是将Add函数作为类A的友元,
注意该函数只能在类A的外部定义
3.即A可以访问Add函数,对a,b进行求和。
该例子为外部函数友元
那如果一个外部函数作为多个类的友元函数,代码是完全一样的吗?
不完全一样,需要前向引用声明。
class B;//前向引用声明
class C;
class A
{
public:
A(int i = 0) :m_i(i) {}
friend int Sum(A& a, B& b, C& c);
private:
int m_i;
};
class B
{
public:
B(int j = 0) :m_j(j) {}
friend int Sum(A& a, B& b,C& c);
private:
int m_j;
};
class C
{
public:
C(int k = 0) :m_k(k) {}
friend int Sum(A& a, B& b,C&c);
private:
int m_k;
};
int Sum(A& a, B& b,C&c)
{
return a.m_i + b.m_j+c.m_k;
}
void main()
{
A a(10);
B b(20);
C c(30);
cout << Sum(a, b, c) << endl;
}
分析:
1.在类A、B、C的外部写入了一个公有函数Sum
2.在类A、B、C中均写入friend void Add(A& a, A& b);即就是将Add函数作为类A的友元,
顺序不是第一个的类必须向前引用声明, 否则会出现以下错误:
有若干不同的类,究竟哪个应该放在首个,哪些向前引用声明呢?
class C;
class A;
class B
{
public:
B(int j = 0) :m_j(j) {}
void Sub(A& a, B& b, C& c);
void Print(A& a);
private:
int m_j;
};
class A
{
public:
A(int i = 0) :m_i(i) {}
friend void B::Sub(A& a, B& b, C& c);
friend void B::Print(A&a);
private:
int m_i;
};
class C
{
public:
C(int k = 0) :m_k(k) {}
friend void B::Sub(A& a, B& b, C& c);
private:
int m_k;
};
void B::Sub(A& a,B&b,C&c)
{
cout << a.m_i - m_j +c.m_k<< endl;
}
void B::Print(A&a)
{
cout << a.m_i << endl;
}
void main()
{
A a(10);
B b(20);
C c(30);
b.Sub(a,b,c);
b.Print(a);
}
分析: 一般情况下,把声明函数的类放在前面,函数的定义写在类的外面
class A { public: A(int i = 0) :m_i(i) {} friend void B::Sub(A& a, B& b, C& c); friend void B::Print(A&a); private: int m_i; }
在这段代码中类B的成员函数Sub、Print都作为了类A的友元
class B;
class A
{
public:
A(int a = 0) :m_a(a) {}
void print(B& b);
void test(B& b);
void show(B& b);
private:
int m_a;
};
class B
{
public:
B(int b=0):m_b(b){}
friend class A;
private:
int m_b;
};
void A::print(B& b)
{
cout << "a::print:" << b.m_b << endl;
}
void A::test(B& b)
{
cout << "a::test:" << b.m_b << endl;
}
void A::show(B& b)
{
cout << "a::show:" << b.m_b << endl;
}
void main()
{
A a(2);
B b(10);
a.print(b);
a.show(b);
a.test(b);
}
类A作为类B的友元函数,(在B中写friend class A的意思就是:告诉B,A是它的friend),所以类A可以访问类B中的所有函数,只需在类A中声明。
A、B两类也可以互为友元类
class B;
class A
{
public:
A(int a = 0) :m_a(a) {}
void print(B& b);
void test(B& b);
void show(B& b);
friend class B;
private:
int m_a;
};
class B
{
public:
B(int b=0):m_b(b){}
friend class A;
void Print(A& a);
private:
int m_b;
};
void B::Print(A& a)
{
cout << a.m_a << endl;
}
void A::print(B& b)
{
cout << "a::print:" << b.m_b << endl;
}
void A::test(B& b)
{
cout << "a::test:" << b.m_b << endl;
}
void A::show(B& b)
{
cout << "a::show:" << b.m_b << endl;
}
void main()
{
A a(2);
B b(10);
a.print(b);
a.show(b);
a.test(b);
b.Print(a);
}
A、B互为友元类,即就是,只要声明了,就可以访问友元类的成员函数。
A 是 B 的友元, 并不意味着 B 是A的友元。
class B;
class A
{
public:
A(int a = 0) :m_a(a) {}
void print(B& b);
void test(B& b);
void show(B& b);
private:
int m_a;
};
class B
{
public:
B(int b=0):m_b(b){}
friend class A;
void Print(A& a);
private:
int m_b;
};
void B::Print(A& a)
{
cout << a.m_a << endl;
}
void A::print(B& b)
{
cout << "a::print:" << b.m_b << endl;
}
void A::test(B& b)
{
cout << "a::test:" << b.m_b << endl;
}
void A::show(B& b)
{
cout << "a::show:" << b.m_b << endl;
}
void main()
{
A a(2);
B b(10);
a.print(b);
a.show(b);
a.test(b);
b.Print(a);
}
没有告诉A:B是它的朋友,所以B不能访问A 的私有成员
A是B的友元, B是C的友元, 但A不是C的友元。
class AA
{
public:
friend class BB;
private:
int m_a;
};
class BB
{
public:
friend class CC;
void Show(AA& a);
private:
int m_b;
};
class CC
{
public:
void printf(BB& b);
void test(AA& a);
};
void BB::Show(AA& a)
{
cout << a.m_a << endl;
}
void CC::printf(BB& b)
{
cout << b.m_b << endl;
}
void CC::test(AA& a)//友元是不能进行传递的
{
//cout << a.m_a << endl;//error
}
void main()
{
AA a;
BB b;
CC c;
b.Show(a);
c.printf(b);
c.test(a);//error
}
void CC::test(AA& a)//友元是不能进行传递的
{
//cout << a.m_a << endl;//error
}
* BB是AA 的朋友
* CC是BB 的朋友
//CC不是AA的朋友,不能访问AA的数据成员
Base 类型继承 Object类型, 如果Object 类型是A的友元,但Base类型不是A友 元。
在函数体中访问对象的成员,必须用对象名加运算符“.”加对象成员 名。但友元函数可以访问类中的所有成员,一般函数只能访问类中的公有成员。
可以把它放在类的公有、私有、保护部分,但结果一 样。
如果该友元函数是另一类的成员函数,则其作用域为 另一类的作用域,否则与一般函数相同。