【问题标题】:Encapsulating data so the setter is private and getter is public封装数据,因此 setter 是私有的,getter 是公共的
【发布时间】:2014-06-18 11:04:51
【问题描述】:

我想知道如何最好地在 C++ 中创建一个数据实体,其中“setter”是私有的,“getter”是公共的。即实体的创建者应该能够设置数据,但用户/消费者/客户端只能获取数据。

让我们考虑实体EntityX:

class EntityX
{
  public:
    EntityX(int x, int y) : x(x), y(y)
    {}
    int GetX() const {return x;}
    int GetY() const {return y;}
  private:
    int x,y; // Effective C++ third edition, Item 22: Declare data members private
}

还有一个创建实体并将其返回给客户端的类方法:

const shared_ptr<EntityX> classz::GetEntityX()
{
  shared_ptr<EntityX> entity(new EntityX(1,2));

  return entity;
}

在我看来,这使得 setter 是私有的,getter 是公共的,但是如果数据成员大于 5-10,这个例子是不实用的......你如何制作一个实体类/结构,使得 setter 是“私有的” " 并且 "getter" 是 "public" 的,没有让构造函数接受所有数据成员变量。

提前致谢

【问题讨论】:

  • 我猜只为你不想让别人改变的成员变量提供一个getter成员函数而不是一个setter成员函数。
  • 我不希望实体类包含数据以外的任何内容。类的创建者必须提供所有数据
  • 所以?为什么需要二传手?
  • 您拥有的默认构造函数应该可以满足您的需求。不需要任何设置器,私有的或其他的。
  • 常数或朋友(船)

标签: c++ private encapsulation public data-members


【解决方案1】:

将你的Creator设置为friendclass EntityX怎么样:

   class EntityX
    {
      friend class Creator;
      public:
        EntityX(int x, int y) : x(x), y(y)
        {}
        int GetX() const {return x;}
        int GetY() const {return y;}
      private:
        int x,y; // Effective C++ third edition, Item 22: Declare data members private
    };

更新:

或者你可以使用模板化的友谊,见下面的代码:

#include <iostream>
#include <memory>

template<class T>
class EntityX
  {
  friend T;
  public:
    EntityX(int x, int y) : x(x), y(y) {}
    int GetX() const {return x;}
    int GetY() const {return y;}
  private:
    int x,y; // Effective C++ third edition, Item 22: Declare data members private
  };

struct Creator
  {
    static const std::shared_ptr<EntityX<Creator>> create() 
      {  
      std::shared_ptr<EntityX<Creator>> entity = std::make_shared<EntityX<Creator>>(1,2);
      entity->x = 1;
      entity->y = 2;
      return entity;
      }
  };

int main()
{
  std::shared_ptr<EntityX<Creator>> const E = Creator::create();
  std::cout << E->GetX() << ", " << E->GetY() << std::endl;

  return 0 ; 
}

【讨论】:

  • 因为我不认识所有的创作者......可能有数百个。例如,资源类进行数据库查询并返回 EntityX 类型的数据行。实体类 EntityX 不能查询数据,它只能包含数据,如果有任何意义的话......
  • @user3594184 目前我不确定,但可能是一个 模板化 朋友类,结合一些类似 CRTP 的模式可以工作。
【解决方案2】:

你的 getter 可以返回一个 const& 所以...

public:
int const& Getter();
private:
int const& Setter(int value);

用“setter”和“getter”替换为变量名。所以...

public:
int const& X();
private:
int const& X(int value);

你也可以用这个语法写同样的东西……

const int& X();

只是你想怎么写而已。

祝你好运,希望能帮到你。

【讨论】:

  • 如果Setter是私有的,实体类的创建者不能访问私有函数
  • 谢谢,我想我错过了问题的那一部分。我会重新考虑我的答案
【解决方案3】:

比如:

struct EntityValues
{
   Type1 value1_;
   Type2 value2_;
   (etc for all the members of Entity
};

class Entity
{
  public:
    Entity () : <set default values> 
    {
    }

    // this avoids the sea-of-parameters problem by bundling the data values
    // into a single parameter.  Data can be added to values by name in random order
    // before it is finally used here.
    Entity(const EntityValues & values) : <set members by pulling data from values>
    {

    }

    // individual public getters.
    Type1 getValue1()const { return value1_;}
    <repeat as necessary for other members>

    // get everything at once 
    // (an alternative to individual getters)
    // 
    void exportValues(EntityValues & values) const
    {
       <copy member to values>
    }

    // optional (this violates the "no public setters" constraint
    // but it does it in a controlled manner.
    void update(const EntityValues & values)
    {
       <set members by pulling data from values>
    }

private:
    <setters (if necessary) and members go here
 };

EntityValues 也可以是在Entity 中声明的公共嵌套结构(即struct Entity::Values

【讨论】:

    猜你喜欢
    • 2011-09-12
    • 2017-06-27
    • 2014-07-21
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 2023-04-04
    • 2018-08-06
    • 1970-01-01
    相关资源
    最近更新 更多