【问题标题】:Hide private class members and methods from clients [duplicate]对客户隐藏私有类成员和方法[重复]
【发布时间】:2021-01-16 15:56:18
【问题描述】:

让我把问题说得更具体一些。我的问题是我有一个基类要发送给客户,以便客户可以在他们的末端开发派生类。如何隐藏私有方法和成员?

例如,在以下代码 sn-ps 中,base.h 文件声明了基类,该基类提供了三个私有虚拟方法供客户端在派生类中覆盖。客户端可以不覆盖任何一个或全部。假设客户开发了一个名为“Derived”的派生类,并将“派生”类创建者传递给我,以便我可以在某处创建派生类,例如Base* p_base = new Derived() 并调用 p_base->Execute() 以实际调用虚函数 DoInitialize()、DoExecute()、DoCleanUp() 的客户端实现。

顺便说一句:我不认为不透明的指针会起作用。

在 Base.h 文件中:

  class Base {
        public:
              Base(); 
             ~Base();
        void Execute(); 
    
        private:
        // virtual functions to be overridden by derived classes.
        virtual void DoInitialize() {}
        virtual void DoExecute() {}
        virtual void DoCleanUp() {}
    
        private: 
        // private members and functions that are intended to hide from clients
        std::vector<float> data_; 
        ....
}

在 Base.cpp 文件中

Base::Execute() {
    DoInitialize();
    DoExecute();
    DoCleanUp();
}

在客户端

class Derived : public Base {
     public:
         Derived();
         ~Derived();

     private:
         // overide base class methods 
         void DoInitialize() {}
         void DoExecute() {}
         void DoCleanUp() {}
}

在我的尽头:

void main() {
     Base* p = DerivedCreater(); // creater a Derived class, assumes DerivedCreater() has passed in by clients. 
     p->Execute(); // I want to call the client implementation of DoInitialize(), DoExecute(), and DoCleanUp()
}

【问题讨论】:

  • 我相信 PIMPL 是最好的选择。我没有重新发布链接,因为它是同一主题的另一个问题中的第一个链接。
  • 不透明的m_impl 指向实现的指针,其中m_impl 知道Base 并调用它的虚函数。
  • 我必须重申我的问题并重新发布,因为我之前帖子中的答案完全搞砸了。通常这意味着两个问题之一将作为另一个副本关闭。
  • 您可能对此感兴趣:Template Method Design Pattern.
  • @Ted Lyngmo,更广泛的范围是我们将在后台为 DoExecute() 提供数据输入,用户将实现 DoExecute() 任何他们想要处理的数据。 DoInitialize() 和 DoCleanUp() 实际上是在 Base::Execute() 之外执行的,但在这里我只想简单地问一个问题。

标签: c++ private


【解决方案1】:

你应该有一个接口类。它没有数据成员,只有纯虚函数。客户端可以使用接口类作为基础编写任何类并实现虚函数。他们必须构造对象并向您传递接口指针。然后你可以在不知道它们是如何实现的情况下调用这些虚函数。

如果您希望客户端对象为您携带一个指针,请将该部分作为接口函数(get、set),不要将其作为数据成员添加到接口类中。

在此处查看示例界面:http://coliru.stacked-crooked.com/a/a3c26e8cc0bb4dc4

【讨论】:

  • 这似乎与 OP 想要的相反。 pimpl 似乎更像 OP 所需要的。
  • Pimpl 适用于您想要隔离具体类实现的情况,以便其他代码不受隐藏的 impl 结构或类更改的影响。这里,3个虚函数就是接口。
  • 是的,它们是隐藏数据的接口——使用 pimpl 的原因可能是你想像你说的那样隔离它,但也可能是因为您实际上希望对最终用户隐藏所有实现细节,这是我个人认为 OP 想要的。但是,我认为有点不清楚 如何 将使用它,因为它无法访问示例代码中的 any 基类成员函数。
  • @Khouri Giordano,谢谢您的回答。这似乎是我正在寻找的东西,但我不确定我是否完全理解你的意思。您介意根据问题中的示例代码编写一个简单的示例代码吗?非常感谢。
  • @Charlie 如果您创建的东西可以传递为纯接口,那么您的基类中将不会有隐藏的std::vector&lt;float&gt; data_;
猜你喜欢
  • 2021-01-16
  • 2021-01-17
  • 2015-07-23
  • 2010-09-17
  • 2013-07-07
  • 1970-01-01
  • 2022-11-13
  • 2013-08-13
  • 2011-10-10
相关资源
最近更新 更多