【问题标题】:Please explain how this is implemented请解释这是如何实现的
【发布时间】:2015-04-25 12:49:55
【问题描述】:

我看到和学到的关于封装的知识是,我们可以将数据成员作为私有成员,而成员函数是公共的。

但 C++ Primer 将封装定义为:

实现与接口分离;封装隐藏 一个类型的实现细节。在 C++ 中,通过将实现放在类的私有部分来强制执行封装。

最后一行是令人困惑的部分:将实现放在类的私有部分。通过实现,他的意思是函数定义,对吗?我的意思是,我从未见过一个函数声明为公共(作为原型)并在私有中实现。

我真的很困惑。请用一个简单的例子解释他想说什么。

【问题讨论】:

  • 也许他在谈论 pimpl 模式c2.com/cgi/wiki?PimplIdiom
  • 不,“实现”是指不属于公共接口但用于实现其行为的类成员(数据和函数)。封装它们的一种方法是将它们设为私有。

标签: c++


【解决方案1】:

所解释的概念比您想象的要抽象。 “接口”是“调用者期望对象执行的操作”。从技术上讲,实现是类实际执行这些操作的方式。

例如,参加 List 课程。 使用 List 的代码应该只关心它的接口:addObject()clear()getSize()sort() 之类的东西。

但是List实现——调用者不应该关心的——在如何实现这一点上可能会有很大的不同。例如,数据可以存储为链表。或者也许作为一个动态数组。这是只有List 类需要关心的“私有”实现细节。确实可能会有一个名为reallocate() 左右的private: 方法。调用者永远不应该使用它;这是一个实现细节——不是公共接口的一部分。调用者不应该关心List 是如何分配其存储空间的。

同样,sort() 方法意味着它将对列表中的对象进行排序。就是这个界面。但是实现可以使用任意数量的算法来执行排序。实现是一个私有细节 - 可以在私有方法中完成。无论如何,它对调用者是隐藏的。

template<typename T>
class List
{
public:
    // public members are part of the interface: the externally-visible behavior "contract" your object guarantees.
    void addObject(const T& obj)
    {
        // call private methods to help carry out implementation.
        ensureCapacity(this->sizeAllocated + 1);
        this->sizeAdvertized += 1;
        // ... and copy the object into the right position in this->data...
    }

    size_t getSize() const
    {
        return this->sizeAdvertized;
    }

    // ... other members like clear(), sort()...

private:
    T* data;
    size_t sizeAllocated;
    size_t sizeAdvertized;

    // this needs to be private because it's not part of the interface. Callers
    // should never need to call this.
    void ensureCapacity(size_t requestedCapacity)
    {
        if(sizeAllocated >= requestedCapacity)
            return;// already have enough storage available.

        // ... reallocate this->data, copy existing items to the new array...

        this->sizeAllocated = requestedCapacity;
    }
};

最后要解决你所说的:

我的意思是,我从未见过一个函数声明为公共(作为原型)并以私有方式实现。

“私人”再次比您想象的更抽象。类的实现基本上是总是“私有的”,因为它对调用者是隐藏的。这并不一定意味着private: 访问说明符。这只是意味着它不会暴露给调用者。公共方法的实现符合这种描述。

【讨论】:

  • 感谢您的解释。 :)
【解决方案2】:

你确实可以在一个类中拥有私有函数(方法)。考虑:

class X 
{
public:
  // public interface - this never changes and you provide documentation for it
  void do_something();

private:
  // this private interface is likely to change. consumers of this class
  // are prevented from calling these methods unless they are friends
  void first_private_thing();
  void second_private_thing();

};

// definition
void X::do_something()
{
  // private implementation in public method
  first_private_thing();
  second_private_thing();
}

这个主题还有进一步的扩展,例如:

class Base
{
public:
  // public non-virtual interface
  void do_something();

private:
  // calls private virtual implementation
  virtual void do_something_impl() = 0;

};

// definition:
void Base::do_something()
{
  do_something_impl();
}

【讨论】:

  • 谢谢兄弟。我爱你。但是,这是一个好习惯吗?我浏览了一些教科书和在线资源,但从未见过这样的实现。
  • 另外,如果我像您一样公开声明do_something() 方法,而不是使用二进制范围解析运算符在类外部定义它,我可以在私有区域中定义它吗?会不会是编译错误?
  • 不,没关系。尽管如果可能的话,最好将实现隐藏在 cpp 文件中。接口描述概念,实现细节与使用你的类的人无关,只要你的实现产生广告(记录)的结果。重新教科书...记住那些会做的人,那些不会教的人;)
  • 哦……最后一件事。那么,如果我们按照我在之前的评论中所说的那样做,这意味着什么?一方面,我们将函数声明为公共的,但如果在类之外,我们将其定义为私有的。那么,该功能是否仍然公开?我想是的。
  • Public 和 private 只控制谁可以调用该函数,而不是你是否可以看到它的作用。术语 public 和 private 不适用于函数中的代码(甚至比 private 更私有,因为没有人可以调用它)。完全可以有一个内联定义的私有函数(别人不能调用)(但大家可以看源码)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多