把类的成员函数声明为友元函数,但不能访问私有成员的原因和解决办法

本文详细探讨了在C++中定义类的友元函数时可能出现的两种常见错误,包括在未定义类的情况下声明友元函数以及在友元函数定义时类信息不完整。通过实例分析,解释了错误的原因,并提供了正确的实现方式,即在类外部定义友元函数。同时指出,只有当友元函数需要访问类的私有成员时,才必须在类外定义。最后总结了处理此类问题的策略,即先声明后实现,确保编译顺序正确。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义类X,类Y,在类X中声明类Y的成员函数g()为类X的友元函数

常见的几种错误写法及原因:

错误写法1

class Y;
class X
{
public:
    X(int i) :i(i) {}
    friend void Y::g(X& object);
    void  print()
    {
        cout << i;
    }
private:
    int i;
};

class Y
{
public:
    void g(X& object)
    {
        object.i += 1;
    }
};

结果编译器显示 Y 的成员函数g()无法访问类X的私有成员i:在这里插入图片描述
原因:在类X中声明Y的成员函数为友元时,此时类Y还没有定义。第一行的class Y,仅作为声明告诉编译器有这个类,而不知道这个类究竟包含了什么。所以在类X中声明成员函数g()为友元的语句无效

错误写法2

通过对刚刚写法的分析,我们很容易想到把类Y的定义放到类X前以消除这个错误,但是这样可行吗?

class X;
class Y
{
public:
    void g(X& object)
    {
        object.i += 1;
    }
};
class X
{
public:
    X(int i) :i(i) {}
    friend void Y::g(X& object);
    void  print()
    {
        cout << i;
    }
private:
    int i;
};

此时编译器显示,类Y的成员函数g()仍然无法访问类X的私有成员
在这里插入图片描述

原因与上一个错误类似。在类Y中定义g()函数时,编译器并不知道g()作为了类X的友元,因为此时类X还没有定义,而只是在第一行作了声明。

正确写法:

class X;


class Y
{
public:
    void g(X& object);
};

class X
{
public:
    X(int i) :i(i) {}
    friend void Y::g(X& object);
    friend  class Z;
    friend void h(X& object);
    void  print()
    {
        cout << i;
    }
private:
    int i;
};

void Y::g(X& object)
{
    object.i += 1;
}

通过把成员函数g()的定义写在类外,可以避免出现以上两种情况

总结:
编译器的编译顺序是从上至下,像这种相互使用的用法,只能先声明,最后统一实现。避免了在这一方使用那一方时出现那一方还未定义而报错的情况。

补充:
这是否说明类的友元函数只能在类外定义呢? 答案是 否定的:当定义在类Y里的友元函数不访问类x的私有成员时,这样定义没问题。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值