3

哪个更好:

class Owner
{
public:
    void SomeMethodA()
    {
        _ownee.SomeMethodA();
    }

    int SomeMethodB()
    {
        return _ownee.SomeMethodB();
    }

private:
    Ownee _ownee;
};

或这个:

class Ownee
{
public:
    void SomeMethodA();
    int SomeMethodB();
};

class Owner
{
public:
    Ownee& GetOwnee() const
    {
        return _ownee;
    }

private:
    Ownee _ownee;
};

我似乎记得很久以前读过第一个选项比第二个选项更好,但我不记得为什么。我想说的是因为 Owner 和 Ownee 的用户之间的耦合较少。客户只需要知道所有者的接口而不是所有者的接口,而使用第二种选项时,客户需要知道所有者和所有者的接口。

4

2 回答 2

3

一个人并非在任何方面都优越,在任何情况下。然而,包装接口和封装成员(第一个)通常是更可取的。

一个类和它的成员有特殊的关系。一个类经常使用它的接口来限制功能在它预期的域内运行,它可以用于额外的内部状态验证和提高程序的正确性。

如果封装得当,则Owner可以根据需要更自由地更改其实现或成员。

暴露成员通常会导致更高的耦合,并最终将大量长期维护推到客户端上(导致更多的错误,以及客户端的冗余实现)。一个相当明显的例子:假设Owner有两个成员,并且必须保证线程安全——将这个责任推给客户端并期望客户端在几年的几次变化中实现和维护线程安全是没有意义的. 但是,Owner可以抽象所有这些,并在其实现更改时适当地更改其实现,或防止成员的更改(Ownee)在这方面影响客户端。

当不暴露其成员时,对类(或Owner或)的更改通常对客户端的影响要小得多,并且类 ( ) 为其功能提供了严格、简单的接口。OwneeOwner

“性能”通常被认为是偏爱第二个的理由(“只为客户提供访问者”)。我发现这是没有根据的过度简化。性能可能更好,也可能更糟!在开发非平凡的程序时,它依赖于 C++ 中的很多很多东西。同样,使用锁定示例:第一个和/或有利于公共访问器的不良接口可能需要更多的锁定。同样,优化器具有信息及其成员的局部性。可能有大量的内部实现和方法由Owner-- 如果这在很大程度上是私有的,并且使用静态调度,它可能会导致一组非常小的导出(或内联,如果你喜欢的话)方法。访问器本身可能并没有那么糟糕,但是对被访问者的操作和依赖可能会将大量指令和依赖推送给您的客户端——当您的内部实现Owner可能以单一、紧凑、优化的形式表示所有这些时。在 C++ 中,抽象层在优化时可能非常便宜(如果做得好,通常什么都没有)。在现实世界中,性能是双向的,取决于许多变量。

大多数情况下,我使用第一种形式。当我使用第二种形式时,它通常是:

  • 私人/内部课程。
  • 或作为更大系统的组件(例如元编程)。

阅读:

http://en.wikipedia.org/wiki/Law_Of_Demeter

http://en.wikipedia.org/wiki/Cohesion_(computer_science )

http://en.wikipedia.org/wiki/Coupling_(computer_science )

http://en.wikipedia.org/wiki/Encapsulation_ (面向对象编程)

http://en.wikipedia.org/wiki/Information_hiding

于 2012-08-04T15:42:08.740 回答
0

您正在考虑 Pimpl(指向实现的指针)习语。

一种很好的方法是在头文件中声明实现类并在 .c 文件中定义它;这样可以确保没有人可以通过 .h 包含查看详细信息。

.h 文件

#ifndef object_INCLUDED
#define object_INCLUDED

#include <boost/scoped_ptr.hpp>

class Object
{
public:
    //...
private:

    class ObjectImpl;
    boost::scoped_ptr<ObjectImpl> impl_;
}

#endif

.c 文件

#include "object.h"

//==================================================
// Implementation of ObjectImpl
//==================================================

class Object::ObjectImpl
{

public:

    ObjectImpl(int);
    int value() const;

private:

    int val_;
};

Object::ObjectImpl::ObjectImpl(int val)
    : val_(val)
{}

int
Object::ObjectImpl::value() const
{
    return val_;
}

//==================================================
// Implementation of Object
//==================================================

Object::Object(int val)
    : impl_(new ObjectImpl(val))
{
}
于 2012-08-04T15:40:26.190 回答