【问题标题】:Objects as member variables in a class in C++对象作为 C++ 类中的成员变量
【发布时间】:2015-03-12 15:16:26
【问题描述】:

我想知道将对象实例作为另一个类的成员变量处理的最佳实践是什么。 在阅读了不同的帖子之后,似乎应该避免将对象引用作为成员变量,但我不确定使用指针是否是一个好的解决方案。另一种可能是将const引用作为类构造函数的参数,然后使用复制构造函数初始化成员变量。

  • 处理这种情况的经验法则是什么?
  • 使用share_ptr 作为成员变量怎么样?
  • 如果成员变量引用抽象类怎么办?在这种情况下,是否有其他替代指针或引用的方法?

编辑:

由于问题的答案实际上取决于上下文,因此我将在类成员引用抽象类的情况下指定它。例如,考虑以下实现策略模式的代码:

 class Client{

        // reference to Abstract strategy
        void execute(){
             strategy.doStuff();
        }
 }

 class AbstractStrategy{

 public:
      virtual void doStuff() = 0;
 }

 class ConcreteStrategy{
      void doStuff(){}
 }

由于AsbtractStrategy 具有纯虚函数,因此使其成为Client 成员的唯一方法似乎是使用指针或引用。有更好的解决方案吗?

【问题讨论】:

  • 没有“经验法则”。这完全取决于上下文。无法回答这个问题。
  • 虽然有this
  • 我非常喜欢智能指针。它们使 C++ 成为一个真正可以使用的框架。

标签: c++ pointers reference shared-ptr member-variables


【解决方案1】:

(甚至是原始的)指针肯定没有错。你只需要负责。如果您希望更改它引用的对象,请通过指针实现该成员,否则添加另一个间接级别是没有意义的,将其作为常规成员变量在内存使用和 CPU 时间方面都会更有效.

Person 类应该将其age 成员作为数字,而不是作为指向一个的指针,但一个人的residence 可能是一个指针,用于引用住宅集合中的对象。并且并不总是需要人来管理住宅或使用智能指针,住宅数据层可能完全独立于人员层,住宅与人一起删除没有什么意义,而是应该就空着吧。

这一切都取决于你需要什么,对象需要是某物、拥有某物还是仅仅引用外部的某物。

请记住,间接是有代价的。这就是为什么将age 成员实现为指针毫无意义的原因,人们不会活很长时间,你可以用一个字节来存储年龄,如果你有一个集合,你将一无所获年龄,并且您为每个人引用一个,因为指针通常是 4 或 8 个字节,加上它引用的字节,您会浪费内存和 CPU 时间来检索该内存地址中的数据。但是住宅可能是一个大对象,加上它与人的耦合并不紧密,因此将人的住宅实现为指针是有意义的。虽然智能指针会在人被删除时删除住所,但常规指针只允许您从该人的析构函数中的住所的居民引用中取消注册该人。

还要考虑这一点——你可能在对象之间有抽象,例如你可能不希望每个人都有一个住宅指针,或者在多个住宅的情况下有多个,实际上一个人可能对存在的一无所知一个住宅,您仍然可以通过使用第三个对象来建立一个人与住宅之间的关系,而无需保留诸如成员之类的对象,例如对象和住宅指针的地图,因此您可以通过以下方式获取一个人的住宅(如果有)查询地图,它会比为每个人都有一个居住地指针要慢,但它会节省内存,因为它不会为每个人的实例存储居住地指针。可能根本没有住所。

至于抽象类——因为它们不能被实例化,你不能有一个作为成员对象。由于这个想法是定义一个接口,你很可能是一个指针并利用虚拟调度和多态性。请注意,除了聚合之外,您还可以使用继承。如果每个对象只有一个策略,并且每个对象都有它,那么聚合和继承都可以解决问题。在某些对象有多个而其他对象没有的情况下,您可以采用上一段中提到的解耦设计。另请注意,使用继承Strategy::doStuff() 将成为该对象的 vtable 的一部分,这意味着该特定类型的每个对象最终都将执行相同的代码,而使用聚合或其他耦合,可以在每个实例基础上设置策略.

【讨论】:

    【解决方案2】:

    您的问题没有单一的答案。您需要考虑的因素是对象生命周期。如果对象 A 以某种形式“包含”对象 B,则对象 B 需要比对象 A 寿命更长或“发生坏事”。

    智能指针 (shared_ptr, unique_ptr) 让对象 A 强制执行规则,即在对象 A 完成之前不能删除对象 B,因此它们是个好主意。

    将对象 B 复制到对象 A 也为对象 B 的生命周期提供了必要的保证,但您需要注意现在有两个单独的对象 B。这是否可以接受由您决定。

    指针和引用通常是有问题的,因为 A 无法控制 B 的生命周期,但有时程序的整体结构意味着这不是问题。

    总结:了解您的对象生命周期并了解您可以使用哪些工具。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-24
      • 1970-01-01
      相关资源
      最近更新 更多