1.關於友元函數的使用
首先介紹下友元函數的由來:友元函數是爲了在類外的非成員函數去訪問類的私有成員和保護成員的(但是注意,友元函數的增加會破壞類的封裝性,因爲非類的成員函數竟然也可以去訪問
類的私有成員和保護成員了!!)。友元函數是不可以繼承的,也就是說基類A的友元函數,並不能被繼承到其派生類B中,也就是說A的友元函數不能訪問B中自己所增加的成員(但是請注意,是
不能訪問B中新增加的成員,但是還可以訪問B中的基類的成員的!!!!)下面就拿幾個例子來說明一下:
(1):普通類的友元函數,可以訪問類的所有成員:
#include <iostream>
class A{
friend void printElement(const A &a);
public:
A(int theElement):element(theElement){}
void print(){std::cout<<element<<std::endl;}
protected:
int element;
};
void printElement(const A &a){
std::cout<<a.element;
}
這個printElement友元函數是可以訪問類A中的所有成員的,這是最簡單的一種友元關係。
(2):普通基類和派生類中的友元關係,在派生類中聲明的友元函數(形參是派生類的對象),可以訪問從基類中繼承過來的成員的
class A {
public:
A(int theElement):element(theElement){}
void print(){std::cout<<element<<std::endl;}
protected:
int element;
};
class B : public A{
//測試2,派生類的友元函數可以訪問從基類中繼承過來的成員!!!!!
friend void printElement(const B &a);
public:
B(int theElement):A(theElement){}
void print(){
A::print();
}
};
void printElement(const B &a){
std::cout<<a.element;
}
(3):普通基類和派生類中的友元關係,在基類中聲明的友元函數(是可以訪問基類的成員,也可以訪問派生類從基類中繼承過來的成員的)。
#include <iostream>
class B;
class A {
//基類的友元函數是可以通過派生類的對象去訪問派生類中的基類的友元函數的!!!!
friend void printElement(const A &a);
public:
A(int theElement):element(theElement){}
void print(){std::cout<<element<<std::endl;}
protected:
int element;
};
class B : public A{
public:
B(int theElement):A(theElement),number(10){}
void print(){
A::print();
}
protected:
int number;
};
void printElement(const A &a){
std::cout<<a.element;//
}
注意,如果在printElement中訪問a.number,那麼就是錯誤的,在基類中聲明的友元函數只能訪問基類中的成員,所以不能訪問派生類中的成員(也就是友元是不能被繼承的)!!!
(4):模板基類和模板派生類中的友元關係: 模板派生類的友元函數可以訪問模板基類中的成員函數,但是訪問的時候注意加上模板基類的類作用域解析符
template<typename T>
class A {//沒有亂碼
public:
A(int theElement):element(theElement){}
void print(){std::cout<<element<<std::endl;}
protected:
int element;
};
template<typename T>
class B : public A<T>{
template<typename C> friend void printElement(const B<C> &a);
public:
B(int theElement):A<T>(theElement){}
void print(){
A<T>::print();
}
};
template<typename T> void printElement(const B<T> &a){
std::cout<<a.A<T>::element;
//一定要注意,使用模板基類中的成員的時候一定要加上基類的類作用域解析符!!!!
}
int main()
{
B<int> b(100);
b.print();
//A a(1000);
std::cout<< "Hello world" << std::endl;
std::cout<<"\n";
printElement(b);
return 0;
}
注意,模板派生類訪問從模板基類繼承過來的成員的時候,一定要加上模板基類的類作用域解析符。比如上面的:
template<typename T> void printElement(const B<T> &a){
std::cout<<a.A<T>::element;
//一定要注意,使用模板基類中的成員的時候一定要加上基類的類作用域解析符!!!!
}