目录
1.定义:
1.概念:
2.注意
3.友元的分类:
4.友元函数代码分析:
1.友元函数出现的原因(外部函数友元为例):
2.一个外部函数作为多个类的友元函数
3.成员函数友元:
4.类友元:
5.特点:
1.不具有对称性 :
2.不具有传递性 :
3.不具有继承性:
6.总结:
1.友元函数不是类的成员函数。
2.友元函数不受类中的访问权限关键字限制。
3.某类的友元函数的作用域并非该类作用域。
1.定义:
1.概念:
友元 friend 机制允许一个类授权其他的函数访问它的非公有成员。友元声明以关键字 friend 开头 ,它只能出现在类的声明中, 它们不受其在类体中的 public private 和 protected 区的影响.。
通俗来说就是就是让函数或者类作为另外一个类的朋友,则可以访问当前类的private或者protected类。
2.注意
1.一个普通函数作为类的友元,那么在当前函数中就可以通过对象访问类的私有或者保护成员
注意:这个函数只能在外部定义,在当前类中引用即可
2.一个类的成员函数作为另外一个类的友元
注意:成员函数建议放在类外定义
3.一个类A作为另外一个类B的友元类,则A的所有的成员函数就可以访问B的私有数据成员或者保护
3.友元的分类:
友元分为外部函数友元, 成员函数友元,类友元。
4.友元函数代码分析:
1.友元函数出现的原因(外部函数友元为例):
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进行求和。
该例子为外部函数友元
2.一个外部函数作为多个类的友元函数
那如果一个外部函数作为多个类的友元函数,代码是完全一样的吗?
不完全一样,需要前向引用声明。
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的友元,
顺序不是第一个的类必须向前引用声明, 否则会出现以下错误:
3.成员函数友元:
有若干不同的类,究竟哪个应该放在首个,哪些向前引用声明呢?
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的友元
4.类友元:
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互为友元类,即就是,只要声明了,就可以访问友元类的成员函数。
5.特点:
1.不具有对称性 :
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 的私有成员
2.不具有传递性 :
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的数据成员![]()
3.不具有继承性:
Base 类型继承 Object类型, 如果Object 类型是A的友元,但Base类型不是A友 元。
6.总结:
1.友元函数不是类的成员函数。
在函数体中访问对象的成员,必须用对象名加运算符“.”加对象成员 名。但友元函数可以访问类中的所有成员,一般函数只能访问类中的公有成员。
2.友元函数不受类中的访问权限关键字限制。
可以把它放在类的公有、私有、保护部分,但结果一 样。
3.某类的友元函数的作用域并非该类作用域。
如果该友元函数是另一类的成员函数,则其作用域为 另一类的作用域,否则与一般函数相同。