友元

C++中的友元为数据隐藏这堵不透明的墙 开了一个小孔,外界可通过这个小孔窥 视类内部的秘密,友元是一扇通向私有 成员的后门
友元可分为:友元函数 友元成员 友元类
 
友元函数不是当前类的成员函数,而是独立于当前类的外部函数,但它可以访 问该类的所有对象的成员,包括私有成 员和公有成员
在类定义中声明友元函数时,需在其函 数名前加上关键字friend。此声明可以 放在公有部分,也可以放在私有部分。 友元函数可以定义在类的内部,也可以 定义在类的外部
友元的利弊
友元不是类成员,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。不过,类的访问权限确实在某些应用场合显得有些呆板,从而容忍了友元这一特别语法现象。
 
友元函数
class Girl {
    char *name;
    int age;
public:
    Girl(char *name, int age):age(age) {
        this->name = new char[strlen(name) + 1];
        strcpy(this->name, name);
    }
    friend void disp(Girl &); //声明为友元函数
};
 
void disp(Girl &x) {
    cout<<x.name<<endl;
    cout<<x.age<<endl;
}
Girl girl("zhangsan", 10);
disp(girl);
友元成员
// 使用友元成员函数访问另一个类
#include <iostream>
#include <cstring>
 
using std::cin;
using std::cout;
using std::endl;
 
class Girl;            //向前引用
//class Boy;
class Boy{
private:
    char *name;
    int age;
public:
    Boy(char *N,int A){
        name = new char[strlen(N)+1];
        strcpy(name,N);
        age = A;
    }
    void disp(Girl &);    //声明disp()为类boy的成员函数
    ~Boy(){
        delete name;
    }
};
 
class Girl{
private:
    char *name;
    int age;
public:
    Girl(char *N,int A){
        name = new char[strlen(N)+1];
        strcpy(name,N);
        age = A;
    }
    friend void Boy::disp(Girl &);    //声明类boy的成员函数disp()为类girl的友元函数
    ~Girl(){
        delete name;
    }
};
 
void Boy::disp(Girl &x)
{    
    cout<<"boy\'s name is:"<<name<<",age:"<<age<<endl;  //访问本类对象成员
    cout<<"girl\'s name is:"<<x.name<<",age:"<<x.age<<endl;  //访问友元类对象成员
}
 
int main()
{
    Boy b("chen hao",25);
    Girl g("zhang wei",18);
    b.disp(g);
    return 0;
}
友元类
//boy为girl的友元类
#include <iostream>
#include <cstring>
 
using std::cin;
using std::cout;
using std::endl;
 
class Girl;
 
class Boy{
private:
    char *name;
    int age;
public:
    Boy(char *n,int d){    
        name = new char[strlen(n)+1];
        strcpy(name,n);
        age = d;
    }
    void disp(Girl &);        //声明disp()为类boy的成员函数
    void test(Girl &g);
 
    ~Boy(){
        delete name;
    }
};
 
class Girl{
private:
    char *name;
    int age;
    friend class Boy;            //声明类boy是类girl的友元
public:
    Girl(char *n,int d){
        name = new char[strlen(n)+1];
        strcpy(name,n);
        age = d;
    }
    ~Girl(){
        delete name;
    }
};
 
void Boy::disp(Girl &x)        //定义函数disp()为类boy的成员函数,也是类girl的友元函数
{    
    cout<<"boy\'s name is:"<<this->name<<",age:"<<age<<endl;
    cout<<"girl\'s name is:"<<x.name<<",age:"<<x.age<<endl;
}
    
void Boy::test(Girl & g)
{
    cout<<"in boy test "<<g.name<<endl;
}
 
int main()
{    
    Boy b("chen hao",25);
    Girl g("zhang wei",18);
    b.disp(g);
    b.test(g);
    return 0;
}
 
注意事项
(1)友元关系不能被继承。
(2)友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
(3)友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明

转载于:https://www.cnblogs.com/gschain/p/11245000.html

<think>好的,我现在需要回答用户关于C++函数和类的定义及使用方法的问题。首先,我需要回忆自己关于的知识,并确保理解正确。 首先,函数是什么?根据引用中的内容,函数是一个普通函数,不属于类的成员函数,但可以访问类的私有和保护成员。比如在引用[1]的示例代码中,`geta`函数被声明为类A的,因此可以直接访问A的私有成员a。同时,引用[3]提到函数需要在类内部声明,使用`friend`关键字,然后在类外定义。这一点很重要,声明函数的位置在类的内部,而定义则可以在外部。 然后是类。类意味着另一个类的所有成员函数都可以访问当前类的私有和保护成员。例如,如果类B是类A的类,那么B的所有函数都能访问A的私有成员。这在引用[2]和引用[1]中都有提到,但具体的例子可能需要进一步补充。 接下来,用户可能想知道如何正确使用函数和类。例如,在引用[4]中,提到了函数的定义格式,但用户需要注意函数并不是成员函数,所以定义时不需要使用类作用域运算符(即不需要`类名::`)。不过,这里可能存在混淆,因为引用[4]的说法可能有误,正确的函数定义应该是在类外作为普通函数定义,而不是用类名限定。比如引用[3]中的`showX`函数,定义时并没有使用`MyClass::`,而是直接作为全局函数定义。所以需要纠正引用[4]中的描述,可能是用户引用中的错误信息。 此外,的使用场景和注意事项也需要说明。比如,破坏了封装性,应谨慎使用。通常用于运算符重载或某些需要跨类访问的情况。比如重载`<<`运算符时,常将其声明为函数,以便访问私有成员输出内容。 在回答时,需要结构清晰,分点说明函数和类的定义、使用方法,并给出示例代码。同时,结合引用的内容,正确引用来源,例如引用[1]、引用[3]中的代码示例,引用[2]中的定义解释等。 还要注意用户提供的引用中有可能存在错误,需要仔细核对。例如引用[4]提到的函数定义格式是否准确,根据C++标准,函数如果是全局函数,定义时不需要类名限定,而如果是另一个类的成员函数作为,则定义时需要相应的类名限定。所以可能需要更详细地解释这一点,避免用户误解。 最后,生成相关问题,确保问题与主题相关,能够帮助用户进一步学习,比如的优缺点、使用场景、与成员函数的区别等。</think>### C++函数与类详解 #### 一、函数 1. **定义** 函数是一个**非成员函数**,但被声明为类的后,可以直接访问该类的私有(`private`)和保护(`protected`)成员。通过在类内使用`friend`关键字声明,例如: ```cpp class MyClass { private: int x; public: friend void showX(MyClass obj); // 声明函数[^3] }; ``` - **关键点**:函数不是类的成员函数,没有`this`指针,需通过对象参数访问成员。 2. **用法示例** ```cpp #include <iostream> using namespace std; class A { public: A(int _a) : a(_a) {} friend int geta(A &ca); // 声明函数[^1] private: int a; }; // 定义函数(无需类作用域::) int geta(A &ca) { return ca.a; // 直接访问私有成员a } int main() { A a(3); cout << geta(a) << endl; // 输出3 return 0; } ``` - **说明**:`geta()`在类外定义,但能访问类A的私有成员`a`[^1]。 --- #### 二、类 1. **定义** 类是指一个类(如`B`)被声明为另一个类(如`A`)的后,**类B的所有成员函数**均可访问类A的私有和保护成员。 ```cpp class A { friend class B; // 声明类[^2] private: int secret; }; class B { public: void revealSecret(A &obj) { cout << obj.secret; // 直接访问A的私有成员 } }; ``` 2. **使用场景** - 当两个类需要紧密协作(如数据结构和其迭代器)时。 - 需跨类操作私有数据,但又不希望暴露给全局函数。 --- #### 三、注意事项 1. **封装性破坏** 机制破坏了封装性,过度使用会导致代码耦合性高,应谨慎使用[^3]。 2. **单向性** 关系是单向的。例如,若`B`是`A`的类,`A`不自动成为`B`的。 3. **不可继承** 关系不可继承,子类不会自动成为父类的。 --- #### 四、典型应用场景 1. **运算符重载** 例如重载`<<`运算符实现自定义输出: ```cpp class Point { private: int x, y; public: friend ostream& operator<<(ostream &os, const Point &p); }; ostream& operator<<(ostream &os, const Point &p) { os << "(" << p.x << ", " << p.y << ")"; // 访问私有成员 return os; } ``` 2. **跨类协作** 如树(`Tree`)类与节点(`Node`)类,节点类可能需要访问树的私有成员。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值