【问题标题】:C++ Have two child classes share a variable from their base classC++ 让两个子类共享一个来自其基类的变量
【发布时间】:2013-12-20 00:21:18
【问题描述】:

假设我有 3 个类:Base、A 和 B。

Base 是 A 类和 B 类的基类。

Base 有一个变量 val,A 和 B 可以访问。

在我可以通过 A 类设置 val 变量并反映在 B 类中的情况下,我如何让它工作?

例如:

我知道下面的这段代码行不通,因为我正在创建一个 a 和 b 类型的 OBJECT。

我想要做的是简单地让 a 和 b 共享同一个变量,这样每当a 对其进行操作时,它就会反映在b 中。

a aa;
b bb;

aa.SetVal(50000);
cout << aa.GetVal() << endl;
cout << bb.GetVal() << endl;

最后我希望cout 两行都打印出 50000。

编辑:A 类和 B 类将执行不同的操作,只需要能够访问/更改 base 中的 val 变量

【问题讨论】:

  • 您必须了解,为aabb 的基类子对象分配的成员的内存位置位于不同的内存位置。共享意味着从不同的地方访问相同的内存位置,这是标准继承无法实现的,除非您选择操作静态基类成员 - 您现在可以在答案中看到后者的几个示例。问题是,这是否是正确的设计,如果您实际操作的值应该是“无实例”值。
  • 我刚刚发布了我打算做的编辑。我需要 a & b 类来访问相同的变量并更改它。
  • 当您说“A 类和 B 类将执行不同的操作”时,这是否意味着 AB 实际上是不相关的类型?那只是因为需要有类似的接口?
  • 是的,它们是不相关的类型。他们唯一需要的共同点就是访问同一个变量。
  • 请看,不相关的类型应该继承自一个常见的Base 类。继承对“is-a”关系建模——这意味着AB 将是共享公共属性的类型,因为它们是相似的。显然它们不相等,但它们都是Base。仅仅为了共享一个静态类成员而继承是不好的设计——实际上我宁愿使用一个隐藏良好的全局而不是这样的设计。

标签: c++ class inheritance polymorphism


【解决方案1】:

这是references 的工作,而不是课程。只需要一个类X 并创建对该对象的引用:

X  aa;
X& bb = aa;
aa.SetVal(50000);
std::cout << aa.GetVal() << std::endl;
std::cout << bb.GetVal() << std::endl;

输出将是:

50000
50000

请记住始终使用正确的工具来完成工作并保持简单。


主要目标是这两个类将做不同的事情,但需要能够访问和共享单个变量。

解决这个问题的一个想法是提取另一个类中的公共变量,即S,它将像这样传递给AB

std::shared_ptr<S> s = new S();
A aa(s);
B bb(s)

现在,aabb 共享同一个 S 对象并且可以很容易地修改它。注意AB 的构造函数也应该存储std::shared_ptr&lt;S&gt;

class A { // and B
private:
    std::shared_ptr<S> s;
public:
    A(std::shared_ptr<S> as) : s(as) {}
};

只要aabb 中的任何一个活着,变量s 就会持续存在:当aabb 都被释放或超出范围时,变量s 也将被释放。

如果公共变量的类型应该在堆栈上,您也可以只使用引用,但要注意aabb 和该变量的生命周期:

int s = 0;
A aa(s);
B bb(s);

与:

class A { // and B
private:
    int& s; // or any other type
public:
    A(int& as) : s(as) {}
};

但作为一般经验法则,我会避免对象之间的共享状态。大多数情况下,您可以根据上下文重构代码并摆脱共享依赖项。

【讨论】:

  • 如果我需要让每个班级(A&B)做不同的事情怎么办?
  • @Sempus,如果两个完全不同的类共享相同的状态,那么你做错了。阅读封装,让你的类尽可能的干净和相互独立。
  • 主要目标是这两个类将做不同的事情,但需要能够访问和共享单个变量。
【解决方案2】:

如果共享值在基类中是静态的,那么派生类的所有实例都将准确地看到那个基类成员。

如果值不是静态的,那么无论值是否在基类中,类的每个实例都会有自己的副本。

【讨论】:

    【解决方案3】:

    您可以使该成员成为基类的静态成员,然后所有派生类都可以访问它,但是任何更改静态成员的派生对象都会为每个其他对象更改它。

    class Base
    {
    public:
    
        int GetVal()
        {
            return val;
        }
    
        void SetVal( int newVal )
        {
            val = newVal;
        }
    private:
    
        static int val;
    };
    
    // Need to instantiate the static variable somewhere
    int Base::val = 0;
    
    class A : public Base
    {};
    
    class B : public Base
    {};
    

    【讨论】:

      【解决方案4】:
      class Base {
          static int value;
      public:
          virtual ~Base() { }
      
          void setVal(const int& val) {
              value = val;
          }
      
          int getVal() const {
              return value;
          }
      };
      
      int Base::value = 0;
      
      class A : public Base {
      };
      
      class B : public Base {
      };
      
      #include <iostream>
      
      int main() {
          A a;
          B b;
          a.setVal(20);
          std::cout << b.getVal(); // 20
      }
      

      【讨论】:

      • 太棒了!我得到了这个工作。现在我只需要将它们移动到不同的文件并让它工作。
      【解决方案5】:

      不确定我是否理解您要执行的操作。您是否希望 A 和 B 的所有实例共享相同的值?如果是这样,请在基类中将其声明为静态。 如果没有,你想如何选择哪一个来分享价值?

      【讨论】:

        猜你喜欢
        • 2015-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-17
        • 2018-09-16
        • 2016-02-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多