开发者社区> 问答> 正文

类成员函数当友元函数,编译错误?报错

1.环境:Win7 + codeBlock + gcc

2.问题:友元函数报错

--------------

G:\projects\friendFun2\A.h|11|error: 'B' has not been declared|
G:\projects\friendFun2\A.h||In member function 'void B::bPrint(A)':|
G:\projects\friendFun2\A.h|14|error: 'int A::m_A' is private|
G:\projects\friendFun2\B.cpp|17|error: within this context|
||=== Build finished: 3 errors, 0 warnings ===|

--------------

代码分为A.h,A.cpp,B.h,B.cpp,main.cpp

A.h


#ifndef A_H
#define A_H

#include "B.h"

class A
{
    public:
        A(int );
        virtual ~A();
        friend void B::bPrint(A aa);
    protected:
    private:
        int m_A;
};

#endif // A_H

B.h


#ifndef B_H
#define B_H


#include "A.h"


class B
{
    public:
        B();
        virtual ~B();
        void bPrint(A aa);
    protected:
    private:
};


#endif // B_H

B.cpp


#include "B.h"
#include <iostream>


using namespace std;
B::B()
{
    //ctor
}


B::~B()
{
    //dtor
}


void B::bPrint(A aa)
{
    cout << "in B :" << aa.m_A << endl;
}

A.cpp没什么好说的。


但是如果和在一个main.cpp的话,就没有上面的问题


#include <iostream>


using namespace std;
class A;


class B
{
    public:
        void bPrint(A aa);
};


class A
{
    public:
        friend void B::bPrint(A aa);
        A(int a):m_A(a){};
    private:
        int m_A;
};


void B::bPrint(A aa)
{
    cout << "in B :" << aa.m_A << endl;
}


int main()
{
    B b;
    A a(6);
    b.bPrint(a);
    return 0;
}




展开
收起
爱吃鱼的程序员 2020-06-14 16:26:04 645 0
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB

    首先你需要了解不完整的类型的概念,要不然你根本不明白那个顺序的原理。

    不完整的类型指的是那种声明了,但是缺少具体定义的类型。比如你最后一段代码第5行。

    这时候重要的是,什么时候可以用不完整的类型,什么时候不可以用。

    你最后一段代码第11行,这部分是声明,所有A是不完整的类型,所以无所谓。

    18行,这里B必须是完整的类型,否则B的成员函数是访问不了的。

    25-28行,这里的实现需要A是完整的类型,所以必须放在A的定义之后。


    所以是这样的:

    #ifndefA_H#defineA_H#include"B.h"classA{public:A(inta):m_A(a){};virtual~A(){};friendvoidB::bPrint(Aaa);protected:private:intm_A;};#endif//A_HA.h不用改,为了编译,直接补上了实现。

    #ifndefB_H#defineB_HclassA;classB{public:B();virtual~B();voidbPrint(Aaa);protected:private:};#endif//B_H直接声明classA,而不是#include。

    #include"B.h"#include"A.h"#include<iostream>usingnamespacestd;B::B(){//ctor}B::~B(){//dtor}voidB::bPrint(Aaa){cout<<"inB:"<<aa.m_A<<endl;}



    到B.cpp,必须#include"A.h",因为后面B::bPrint的实现需要完整的A的定音。


    回复 @linch:include这个东西一定不要和类联系起来,更多的是应该是类似复制粘贴的行为。用gcc-E展开宏调用应该可以帮助你理解(电脑上没gcc,我也不太确定参数对不对)用你的方法改后编译通过了。非常感谢!顺便问一下,预编译#include"A.h"这个可以认为会调用A的定义吗?

    看Primer的时候发现这个问题。

    然后百度到下面这个顺序:

    先声明A->定义B类->定义A类->定义友元函数.

    但A和B类不在一个文件时,就悲剧了。

    C++大神帮忙看看

    2020-06-15 11:06:04
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载

相关实验场景

更多