Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Getter vs public成员以及替换返回对象的可能性_C++_Pointers_Getter Setter - Fatal编程技术网

C++ Getter vs public成员以及替换返回对象的可能性

C++ Getter vs public成员以及替换返回对象的可能性,c++,pointers,getter-setter,C++,Pointers,Getter Setter,我最近与一位同事就getter&setter进行了一场辩论,getter&setter使用指针来对抗公共成员指针(该主题导致了同样的辩论,没有指针,而是让getter返回引用)。我不确定这个话题是否会重复,但在寻找这个话题的答案时,我发现只有三个话题(,和)与“getter/setters vs public member”这个话题相关,但没有指出我们辩论的方向 因此,情况如下: //example for TextProperties class TextProperties { protec

我最近与一位同事就getter&setter进行了一场辩论,getter&setter使用指针来对抗公共成员指针(该主题导致了同样的辩论,没有指针,而是让getter返回引用)。我不确定这个话题是否会重复,但在寻找这个话题的答案时,我发现只有三个话题(,和)与“getter/setters vs public member”这个话题相关,但没有指出我们辩论的方向

因此,情况如下:

//example for TextProperties
class TextProperties
{
protected:
  int m_size;
  bool m_bold;

public:
  bool Bold() { return this->m_bold; }
  void Bold(bool bold) { this->m_bold = bold; }
  int  Size() { return this->m_size; }
  void Size(int size) { this->m_size = size; }

  TextProperties()
  {
    this->m_bold = false;
    this->m_size = 5;
  }

  ~TextProperties() {}
}

//example for Text
class Text
{
protected:
  TextProperties* m_properties;

public:
  TextProperties* Properties() { return this->m_properties; }
  void            Properties(TextProperties* properties) { this->m_properties = properties; }

  Text()
  {
    this->m_properties = new TextProperties();
  }

  ~Text()
  {
    delete this->m_properties;
  }
}

//the usage as I want it:
int main()
{
  Text* exampleText = new Text();

  //easily and short a property gets changed
  exampleText->Properties()->Bold(true);

  delete exampleText;
}
有一个类
Text
Text
类型的对象始终包含另一个
TextProperties
类型的对象(例如大小、颜色、粗体、斜体、下划线等)。要修改属性,我想直接使用
TextProperties
-对象的方法,而无需创建新对象。这最终导致getter返回
TextProperties
-对象的指针

下面是一个非常简单的例子:

//example for TextProperties
class TextProperties
{
protected:
  int m_size;
  bool m_bold;

public:
  bool Bold() { return this->m_bold; }
  void Bold(bool bold) { this->m_bold = bold; }
  int  Size() { return this->m_size; }
  void Size(int size) { this->m_size = size; }

  TextProperties()
  {
    this->m_bold = false;
    this->m_size = 5;
  }

  ~TextProperties() {}
}

//example for Text
class Text
{
protected:
  TextProperties* m_properties;

public:
  TextProperties* Properties() { return this->m_properties; }
  void            Properties(TextProperties* properties) { this->m_properties = properties; }

  Text()
  {
    this->m_properties = new TextProperties();
  }

  ~Text()
  {
    delete this->m_properties;
  }
}

//the usage as I want it:
int main()
{
  Text* exampleText = new Text();

  //easily and short a property gets changed
  exampleText->Properties()->Bold(true);

  delete exampleText;
}
我的同事反对这种解决方案,因为使用这种解决方案,可以在绕过任何setter的同时打开门来替换对象(在使用引用返回getter时也是如此)

//An example for the replacing bypassing the setter:
int main()
{
  Text* exampleText = new Text();

  //easily and short a property gets changed
  exampleText->Properties()->Bold(true);

  TextProperties* test = exampleText->Properties();
  *test = *(new TextProperties());
  //at this point the text wouldn't be bold

  delete exampleText;
}
据我所知,唯一可能安全的解决方案(对象不能被另一个对象替换)是返回
const
,并强制使用该类的任何人创建一个新的
TextProperties
-对象以仅更改一个属性。如前所述,这种解决方案是不可取的

//just as intimation how the other, replacing safe 
//way of usage I want to avoid could look:
int main()
{
  Text* exampleText = new Text();

  //if needed copy-construct the object otherwise just use (default) constructor
  TextProperties* newProperties = new TextProperties(exampleText->Properties()); 
  newProperties->Bold(true);
  exampeText->Properties(newProperties);

  delete exampleText;
}
到目前为止的情况-现在的辩论:

接受能够直接修改属性的目标我的同事than提到,他认为解决方案对公众成员没有区别。
我的观点如下:

  • 使用getter/setter可以隐藏内部(=封装)
    • 内部更改可以更容易/更快地执行,因为公共成员访问分散在所有源代码中
    • 也可能是带有前缀和/或后缀的难看的内部名称被一个漂亮且易于描述的名称覆盖(例如,内部:int m_x,m_y外部:Width(),Height()(是的,人们会这样做))使使用类的代码更清晰、更容易理解
  • 通过提供getter/setter,类使用者可以确保以应该的方式完成任务(对于我来说,只有public member对于int等简单类型才有意义。因为更复杂的对象可能需要一些特定的操作,例如确保所包含信息的正确性)此外,该构件还受到保护,防止因错误而进行修改
  • 如果有人想在绕过getter的同时替换对象,他必须故意这样做,因此当代码不能按预期工作时,这是他的错,此时我的任务只包括确保不会发生损坏(但这始终是我的任务)->如果你想强制执行某些事情,你可以执行。。。好或坏这是另一个问题,C++没有处理,它只是给出了可能性;李>
  • 避免按值复制时,不需要复制对象,这可以但不一定是性能增益(通过编辑添加的点)
  • 当以可编辑的方式访问对象并直接更改所访问对象的成员时,它(对我来说)较短且易于理解的源代码(通过编辑添加的点)
我认为前两点主要是来自经典的getter/setter和public成员讨论的争论。无论如何,这场争论并没有改变我同事的观点,我现在对这个话题沉思了好几天。所以我想知道是否真的没有区别(我个人肯定会说“这是一个区别”),这些论点只是我的主观观点,这是个人品味的问题,是否存在更具说服力的论点(对于两种观点),或者存在完全不同的解决方案,不会引起讨论

编辑:除了问题之外,我想更多地指出问题的重点(根据答案上的说明),并指定问题本身:
如果已经决定使用getter和setter,并且使用引用或指针破坏了getter的封装:为什么这仍然比使成员成为公共成员更好?(我试图提供拥有这些getter的列表参数,我想知道这些参数中哪些是in/valid,哪些是pro/contra,这些getter或public成员)


希望这不是重复,我期待一些有趣的答案。谢谢!:)

返回指向私有成员的指针或引用的一些潜在问题:

  • 正如您所提到的,封装被破坏了。您已直接授予该成员访问权限,尽管它是私有的
  • 如果
    Text
    类在其
    TextProperties
    成员上保留一些不变量,则这些不变量可能会通过从类外部修改对象而失效
  • 客户机代码必须知道,只有当返回该引用的
    文本
    对象仍处于活动状态时,该引用才有效
正如你的朋友所说,如果你把会员公之于众,这些都是真的。然而,您可能想做一些额外的工作来简单地返回成员(比如维护那些不变量)

有时,如果您真的想要如您所描述的那样的接口,这些是必须处理的问题。对于实践中的例子,请看一看-它返回对元素的引用。请注意,此函数和您的函数的语义是不同的,但是-
std::vector
是一个容器,因此
operator[]
将公开其中包含的元素(就像在数组上使用
[]
一样)。相反,您正在公开
文本的某些状态