C++友元类的详细解析

发布时间:2023-05-21

一、友元类的概念

在C中,类(包括其对象)拥有访问限制,即如果在类的外部定义的函数或对象想要访问类的私有或保护成员,需要借助于公有成员函数。这种限制保护了类的封装性,但是也带来了一定的不便。 为了能够方便地访问类的私有或保护成员,C引入了友元类(friend class)的概念。

class A{
private:
    int n;
public:
    void func();
    friend class B;//友元类声明
};
class B{
public:
    void func(A &a);//B类通过A类对象,直接访问A类的私有成员n
};

二、友元类的作用

友元类能够访问另一个类的私有或保护成员,这意味着,我们可以把多个类放在一起,让它们互相访问和操作彼此的私有成员,也就是说,友元类提供了一种控制类之间访问权的机制,增强了类之间的灵活性和多样性。 例如,在图形学中,我们需要定义许多类表示不同的图形对象,每个类都必须维护自己的一套数据和操作,但是它们之间也需要互相引用和操作,那么这时候友元类就非常有用,可以使得每一个图形对象得到需要的信息,进行相应的操作。

三、友元类的使用

要使用友元类,需要在类的定义中声明友元类,这样在友元类中就可以直接访问当前类的私有和保护成员了。 需要注意的是,友元类的声明只是为了让这个类能够直接访问当前类的私有和保护成员,但并不意味着当前类也能访问友元类的私有和保护成员。 下面的例子中,类B是类A的友元类,能够直接访问类A的私有成员func1()。但是类A并不是类B的友元类,所以不能直接访问类B中的私有成员func2()。

class B;
class A{
private:
    int n;
    void func1(){
        n = 1;
    }
public:
    friend class B;
};
class B{
private:
    int m;
    void func2(){
        m = 2;
    }
public:
    void func(A &a){
        a.func1();
    }
};

四、友元类的注意事项

  1. 友元关系不能被继承。即使子类继承了父类的友元类,也不能访问父类的私有成员。
  2. 友元关系是单向的。如果类A是类B的友元类,不代表类B也是类A的友元类。
  3. 友元类和友元函数具有相同的权限特点,都能够直接访问当前类的私有成员,但是这样做会破坏类的封装性,不利于代码复用和维护,应该谨慎使用。

五、实战演练

下面通过一个实际的例子来演示友元类的使用。 假设我们需要设计一个游戏角色类(Character),其中包括角色的基本属性和攻击方式。同时,我们需要设计一个技能类(Skill),其中包括技能的名称和伤害值。 技能类需要能够直接访问角色类的私有成员,以便于计算技能的攻击伤害。

class Character;//前置声明,以便于Skill类中的访问
class Skill{
private:
    int damage;
    string name;
public:
    Skill(int d, string n){
        damage = d;
        name = n;
    }
    void attack(Character &c);
};
class Character{
private:
    int hp;
    int mp;
    friend class Skill;//友元类声明,Skill类可以访问Character类的私有成员
public:
    Character(int h, int m){
        hp = h;
        mp = m;
    }
    void display(){
        cout << "HP: " << hp << endl
             << "MP: " << mp << endl;
    }
};
void Skill::attack(Character &c){
    c.hp -= damage;
}
int main(){
    Character c(100, 50);
    Skill s(20, "Fireball");
    c.display();
    s.attack(c);
    return 0;
}

六、总结

友元类是一种让多个类之间互相访问和操作彼此的私有成员的技术。友元类的声明和使用虽然能够方便地处理一些问题,但会破坏类的封装性,不利于代码的维护和管理,应该慎重使用。