我有一个简单容器类副本构造。

你建议使用吸气和制定者、或访问成员变量直接?

public Container 
{
   public:
   Container() {}

   Container(const Container& cont)          //option 1
   { 
       SetMyString(cont.GetMyString());
   }

   //OR

   Container(const Container& cont)          //option 2
   {
      m_str1 = cont.m_str1;
   }

   public string GetMyString() { return m_str1;}       

   public void SetMyString(string str) { m_str1 = str;}

   private:

   string m_str1;
}
  • 在本示例中,所有代码是嵌入式的,但在我们真正的代码有没有内联的代码。

更新(29日09):

这些答复都写得很好但是他们似乎得到的缺点的这样一个问题:

  • 这是简单的人为例子,讨论使用干将/者vs变量

  • 初始化列表或私人验证功能的不是真正的一部分,这个问题。我想知道,如果设计将让代码更易于维护和扩大。

  • 有些人是专注于字符串中的这个例子,然而它只是一个例子,假设这是一个不同的对象。

  • 我不关心的业绩。我们不是编程上的PDP-11

有帮助吗?

解决方案

你预期如何串返回,例如。空白的剪裁,null检查,等等?同SetMyString(),如果答案是肯定的,你是最好的访问的方法,因为你不必改变你的代码,在无数的地方,但是仅仅修改这些吸气器和方法。

其他提示

编辑: 回答的编辑问题:)

这是简单的人为例 讨论使用干将/者vs 变量

如果你有一个简单的收集变量,不需要任何种类的验证,也没有额外的处理,然后你可以考虑使用荚代替。从 Stroustrup的常见问题解答:

一个设计良好的类提出了一个干净的 而简单的接口,以其用户, 隐藏它的代表性 和节约 其使用者从具有知道 这表示。如果的 表示不应该隐藏 说的,因为用户应当能够 改变任何数据成员以任何方式他们 喜欢-你能想到的那类 "只是一个普通的老式的数据结构"

总之,这不是JAVA。你不应该写入普通的干将/者,因为他们是作为糟糕,因为暴露的变他们的自我。

初始化列表或私人验证功能的不是真的 一部分这个问题。我不知道 如果设计将使代码 更易于维护和扩大。

如果你是复制的另一个目的变量,则源的对象应该是在一个有效的国家。怎么没生病的形成来源目得到了建造的第一个地方?!不应该造做的工作的验证?不是修改成员职能,负责维持类不变的通过验证的输入?为什么你会验证的"有效"的对象在一个复制的构造?

我不关心的业绩。我们不是编程上的PDP-11

这是有关最优雅的风格,但是用C++的最优雅的代码拥有最好的性能特征通常。


你应该使用 initializer list.在你的代码, m_str1 是默认构成 然后 分配一个新的价值。你的代码可以像这样的东西:

class Container 
{
public:
   Container() {}

   Container(const Container& cont) : m_str1(cont.m_str1)
   { }

   string GetMyString() { return m_str1;}       
   void SetMyString(string str) { m_str1 = str;}
private:
   string m_str1;
};

@cbrulak你不应该海事组织验证 cont.m_str1copy constructor.我做什么,是要验证的事情中 constructors.验证中 copy constructor 意味着你你是复制一种虐待形成的对象放在第一位,例如:

Container(const string& str) : m_str1(str)
{
    if(!valid(m_str1)) // valid() is a function to check your input
    {
        // throw an exception!
    }
}

你应该使用的一种初始化名单,那么问题就变得毫无意义,因为:

Container(const Container& rhs)
  : m_str1(rhs.m_str1)
{}

有一个很大部分在马修*威尔逊的 不完善C++ 这就解释了所有有关会员初始化列表,和有关如何使用它们结合const和/或引用让你的代码的更加安全。

编辑:一个例子显示出验证和常数:

class Container
{
public:
  Container(const string& str)
    : m_str1(validate_string(str))
  {}
private:
  static const string& validate_string(const string& str)
  {
    if(str.empty())
    {
      throw runtime_error("invalid argument");
    }
    return str;
  }
private:
  const string m_str1;
};

因为它的编写现在(没有资格的输入或输出)你吸气和器(取和突变,如果你愿意)都是实现绝对没有,所以你可能也只是使串公众和用它来完成。

如果真正代码确实符合资格的串的,机会是很好的,什么你处理不是适当地一串在所有--而不是,它只是东西,看起来很像是一串。什么你真的在做这种情况下被滥用的类型系统,有点暴露一个字符串,当实类型是唯一的东西有点像是一串。你然后提供的定者试图强制执行任何限制的实际类型相比,一个真正的串。

当你看着它从那个方向,答案变得相当明显的:而不是弦,a器使串的行为就像一些其他的(限制)的类型,你应该做的反而是确定一个实际的类型你真正想要的。具有定义,这类正确,你做的一个实例,它公开。如果(作为似乎是这里的情况),它的合理分配一个值,开始作为一个弦,然后,这类应该包含一个分配运营商采用字符串作为一个参数。如果(如也似乎是这里的情况),它的合理要转换这种类型字符串在一些情况下,它也可以包括投操作人员产生一个字符串的结果。

这提供了一个真正的改进,在使用定者和吸气在围绕类。首先,当你把那些在围绕类,这很容易用于代码内这类绕过吸气/器,失去强制执行的不管是什么置者应该执行。第二,它保持着一个正在寻找符号。使用吸气器和部队你写的代码,就只是普通的丑恶和难以阅读。

其中一个主要优势之一串类在C++是使用操作者负载过重,因此您可以替换的东西,如:

strcpy(strcat(filename, ".ext"));

有:

filename += ".ext";

提高其可读性。但看看发生什么事情如果这串的类的一部分,迫使我们通过吸气和器:

some_object.setfilename(some_object.getfilename()+".ext");

如果有的话,C代码实际上是更具可读性比这个烂摊子。另一方面,考虑发生了什么,如果我们做的工作的权利,公众对象的类的定义操作者串和操作人员=:

some_object.filename += ".ext";

好的,简单和可读性,就像它应该是。更好的是,如果我们需要执行一些关于字符串中,我们可以检查只有小类,我们真的只要看一个或两个具体、着名的地方(运营商=,可能是一个构造函数或两个用于这一类),要知道,它总是强迫--一个完全不同的故事从当我们使用一定者试图做的工作。

问问你自己什么样的成本和效益。

费用:更高的运行开销。叫虚拟的功能在输入是一个糟糕的想法,但制定者和吸气是不可能是虚拟的。

福利:如果二传/吸气做一些事情复杂,你在不重复代码;如果它做了什么不直观,你不要忘记做到这一点。

成本/效益比例将有所不同于不同类别。一旦你确定比率,用你的判断。对于一成不变的类,当然,你没有制定者,你不需要吸气(作为常量成员和参考文献可以是公共的,因为没有人可以改变/重新安装)。

有没有银子弹头作为如何编写的副本构造。如果你的班级仅有其成员提供一份副本构造,创建 情况不同国家(或者至少不会出现这样做)使用初列表是一个好办法。

否则你会有实际的想法。

struct alpha {
   beta* m_beta;
   alpha() : m_beta(new beta()) {}
   ~alpha() { delete m_beta; }
   alpha(const alpha& a) {
     // need to copy? or do you have a shared state? copy on write?
     m_beta = new beta(*a.m_beta);
     // wrong
     m_beta = a.m_beta;
   }

注意,你可以得到周围的潜在出现段错误的使用 smart_ptr -但是,你能有很多的乐趣,试得到的错误。

当然它可以得到更有趣。

  • 成员创建上的需求。
  • new beta(a.beta)错误的 万一你以某种方式引入多态性。

...一个螺钉 否则 -请总是想当编写一份构造。

为什么你需要吸气,并制定者?

简单:)-他们保持不变--即保证你的类,如"MyString总是有一个甚至数字符"。

如果实施为目的,对象是总是在一个有效的国家这样一个员复制很好可以复制的成员直接没有恐惧的破坏任何保证。有没有优势的通过已经确证的通过又一轮的国家验证。

作为阿拉克说,最好的办法是使用一种初始化名单。


没那么简单(1):
另一个原因是使用吸气/者不是依靠执行情况的详细信息。这是一种奇怪的想法复制构造函数,当改变这种执行情况的详细信息,你几乎总是需要调整CDA无论如何。


没那么简单,(2):
来证明我是错误的,可以建构不变,都依赖于本身的实例,或另一个外部因素。一个(非常contrieved)的例子:"如果数个实例是甚至串的长度甚至,否则就是奇怪的。" 在这种情况下,复制构造函数将不得不放弃,或者调整。在这种情况下,它可能会帮助使用者/吸气-但是那不是一般的cas。你不应该获得的一般规则,从古怪。

我更喜欢使用一个接口,用于外部类访问的数据,如果你想改变它的方式检索。但是,当你范围内的该类和要复制本国家内部的复制的价值,我会去的数据成员。

更不要说你可能会节省一些功能的电话如果吸气都没有内联。

如果你吸气的是(在线)不 virtual, 没有长处,也没有缺点在于使用它们的应用程序直接成员的访问--它只是看起来傻傻的到我的风格,但是,没什么大不了的两种方式。

如果你干将是虚拟的,那么 顶...但尽管如此,这正是当你想要打电话给他们,只要的情况下,他们复盖在一个子类!-)

有一个简单的试验工作的许多设计问题,这其中包括:添加侧重效果,并看到什么样的休息时间。

假设置者不仅分配一个值,而且还写入审计记录,记录的消息,或引发事件。你想让这发生的每一个酒店时的复制的对象?可能不那么叫的制定者在构造逻辑上是错误的(即使制定者是实际上仅分配).

虽然我同意与其他的海报,还有许多条目中级C++"没有没有"在你的样本,将得到一边,并回答你的问题直接:

在实践中,我倾向于使许多但不是我所有的成员域*公开始,然后将它们移动到get/set需要的时候。

现在,我将是第一个来说,这不一定是一个建议的做法,以及许多从业人员会厌恶这和说,每一个领域应该制定者/干将.

也许。但我发现,在实践中,这并不总是必要的。当然,它会导致痛苦后,当我改变的一个领域,从公共来吸气,有时当我知道是什么使用一个类都会有,我给它设置/获得和使该领域受保护的,或者从私人的开始。

情况因人而异

RF

  • 你叫领域"变量的"我鼓励你使用这一术语仅用于当地变量内的职能/方法
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top