如何使用友元函数和继承拆分定义和声明

Posted

技术标签:

【中文标题】如何使用友元函数和继承拆分定义和声明【英文标题】:How to split definition and declaration with friend function and inheritance 【发布时间】:2022-01-01 09:31:11 【问题描述】:

我需要编译这样的东西:

struct Base 
    virtual void func1()=0;
    // ...
    friend void Derived::func2(Base *base);
private:
    int some_private;


struct Derived : Base 
    virtual func3()=0;
    // ...
    void func2(Base *child) 
        std::cout << child->some_private;
    
;

但我不断收到编译错误。我尝试交换结构或先声明它们,但我不能先声明 Derived(因为继承),我不能先声明 Base(因为我需要在 Derived 中声明友元函数)。怎么办?

【问题讨论】:

考虑将整个struct Derived 加为好友,或将private 替换为protected @Frank -- 使some_private protected 不允许child-&gt;some_privatefunc2 中。派生类型的对象可以访问自己的继承的受保护成员,但不能访问其他对象的受保护成员。 你遇到了先有鸡还是先有蛋的问题。您不能在 friend 声明中添加成员函数;编译器必须看到Derived 的定义才能使Derived::func2 有效。与非成员函数不同,friend declaration 也用作该函数的声明。所以,最好的办法是声明Derived 为朋友。 @PeteBecker 感谢您提供的信息,我希望这与 private 访问其他实例的成员保持一致。 @Frank -- 是的,这是自然的期望。 protected 不同,我不记得为什么会这样,但这是有充分理由的。 【参考方案1】:

您有一些基本的解决方案。最明显的就是从私有变为受保护。在 C++ 中,protected 意味着子类可以访问。

您可以添加更多公共(可能是受保护的)访问器方法。

您可以前向引用整个 Derived 类并成为整个类的朋友。

就我个人而言,我从来没有觉得需要使用友元方法或类,而且我不知道我必须在什么情况下才能不依赖其他方法来完成我正在尝试的任何事情完成。

对于这个特定的解决方案,我会将访问权限更改为受保护。

【讨论】:

谢谢,我会让全班都成为朋友,因为我不能让函数受保护。 protected 不起作用。派生类型的对象可以访问它们自己的继承的受保护成员,但不能访问其他对象的受保护成员。 child-&gt;some_private 尝试使用不同对象的受保护成员,因此不允许。 @PeteBecker childBase 类型——超类。所以你是说子类不能访问超类的受保护成员? @JosephLarson -- 不,我不是这么说的。派生类型的对象无法访问另一个对象的受保护成员。 不要将基础 class 与基础 object 混淆。

以上是关于如何使用友元函数和继承拆分定义和声明的主要内容,如果未能解决你的问题,请参考以下文章

友元函数都有哪些特点?

友元的友元类

关于声明定义前向声明include循环依赖普通友元函数友元类友元成员函数的总结

友元函数和友元类

友元相关

Java里有没有友元函数这回事