【问题标题】:Where in derived class or base class should I declare friend class?我应该在派生类或基类中的哪个位置声明朋友类?
【发布时间】:2019-07-07 20:30:13
【问题描述】:

我有一个在 C++ 中实现接口(抽象类)的派生类。这个接口有几个受保护的函数,它们的实现在派生类中定义。

现在我试图通过将外部类声明为派生类中的朋友来从外部类访问派生类中的这些受保护函数。但是,编译器仍然抱怨我无法访问受保护的成员函数。

例如: 我有类ConnectSession 实现IConnectSession。还有一个名为SystemProcess 的外部类想要访问受保护的成员函数HandlePriviledgedRequest

在 IConnectSession.h 中

class IConnectSession{
protected:
    virtual void HandlePriviledgedRequest() = 0;
}

在 ConnectSession.h 中

class ConnectSession : public IConnectSession{
protected:
    void HandlePriviledgedRequest() override {/* func definition */}
    friend class SystemProcess;
}

在朋友班我尝试访问HandlePriviledgedRequest()

SystemProcess.cpp

SystemProcess::ApplyConfiguration(){
    std::shared_ptr<IConnectSession> sessionPtr = new ConnectSession();
    sessionPtr->HandlePriviledgedRequest(); // compile error
}

它从编译器中抛出一个错误,说即使我已经将SystemProcess 声明为朋友,我也无法访问受保护的成员。由于没有继承友元声明,我特别在ConnectSession 中声明它们。为什么它不起作用以及如何解决它?谢谢。

【问题讨论】:

  • 一般来说,我希望接口的成员函数是公开的。为什么这些受到保护?
  • @PeteBecker,我想确保某些接口方法仅在某些类中调用,而在其他类中不调用。所以朋友会员资格只授予那些特定的类。

标签: c++ inheritance polymorphism protected friend-class


【解决方案1】:

访问控制仅适用于编译时。在

SystemProcess::ApplyConfiguration(){
    std::shared_ptr<IConnectSession> sessionPtr = new ConnectSession();
    sessionPtr->HandlePriviledgedRequest(); // compile error
}

即使sessionPtr 被设置为ConnectSession 的一个实例,它的静态类型是IConnectSession,这就是运行访问控制的对象。由于SystemProcess 不是IConnectSession 的朋友,因此不允许访问HandlePriviledgedRequest()

您需要将其设为IConnectSession 的朋友才能编译。

【讨论】:

  • 谢谢。这是有道理的。在基类和派生类中都声明友元类是最佳实践吗??
  • @Vince 最佳实践是通常避免使用友元类作为中断封装,并且通常意味着事物之间存在紧密耦合。在这种情况下,尽管您只需要成为基类的朋友,因为您只访问基类提供的接口。如果您需要将基类转换为派生类以访问仅派生的药水,则您需要成为派生类的朋友。
【解决方案2】:

那是因为您的访问是通过IConnectSession 接口sessionPtr 进行的,而您的友谊只与派生类有关,而不是基类。

【讨论】:

    猜你喜欢
    • 2019-09-15
    • 2018-08-23
    • 2020-08-10
    • 2017-07-04
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    • 2023-03-30
    相关资源
    最近更新 更多