实现层次结构中的冗余私有成员数据复制

时间:2013-01-17 22:24:53

标签: c++ design-patterns

我的问题涉及公共和私有继承的组合,作为在C ++类中分离接口和实现的工具。在此模式中,接口基类声明了公共函数(class Base0)。通常的实现是在几乎从接口库(class Impl0 : virtual public Base0)派生的类中执行的。此类包含任何公共数据成员。扩展类分两步编写。首先,扩展接口由来自接口库(class Base1 : virtual public Base0)的虚拟继承定义。其次,扩展实现是通过从Base1(用于接口)和私有地从Impl0(用于实现)公开导出来执行的:class Impl1 : public virtual Base1, private Impl0。我的问题如下:

(1)如果扩展类中的函数定义了需要Impl0中的公共数据的函数,我是否必须在`Impl1'中复制该数据?

(2)有没有办法避免这种复制?

作为一个最小的例子,考虑一个用于实现四个基本算术函数的类层次结构:add(),substr(),mult()和div()。基本版本MathOps包含add()和subtr()函数。扩展版本MathOps_Extn包含mult()和div()。上述技术给出了以下类层次结构。

#include<iostream>

using std::cout;
using std::endl;

class MathOps {
public:
  virtual int add(int x) = 0;
  virtual int subtr(int x) = 0;
};

class MathOps_Impl : public virtual MathOps {
private:
  int m_y;
public:
  MathOps_Impl(int y) : m_y(y) {
    cout << "MathOps_Impl initialized with value: " << m_y << endl;
  }

  virtual int add(int x) { return x + m_y;}
  virtual int subtr (int x) { return m_y - x;}
};

class MathOps_Extn  : public virtual MathOps {
  // Extends MathOps by adding mult() and div()                                                                                                                                 
public:
  virtual int mult(int x) = 0;
  virtual int div(int x) = 0;
};

class MathOps_Extn_Impl : public    virtual MathOps_Extn, private MathOps_Impl {
private:
  int m_y; // Have to replicate member data m_y here.                                                                                                                           
public:
  MathOps_Extn_Impl(int y) : MathOps_Impl(y), m_y(y) {
    cout << "MathOps_Extn_Impl initialized with value: " << m_y << endl;
  }

  virtual int mult(int x) {
    return x * m_y;
  }
  virtual int div(int x) {
    int quotient = x == 0? 0 : m_y/x;
    return quotient;
  }
};

int main() {                                                                                                                                           
  MathOps_Extn* B =  new MathOps_Extn_Impl(10);
  cout << "add 20: " << B->add(20) << endl;
  cout << "subtr 20: " << B->subtr(20) << endl;
  cout << "mult 2: " << B->mult(2) << endl;
  cout << "div 5: " << B->div(5) << endl;

请注意m_yMathOps_Extn_Impl的复制。有没有办法避免这种复制?

2 个答案:

答案 0 :(得分:1)

  

请注意在MathOps_Extn_Impl中复制m_y。有什么办法吗?   避免这种复制?

是。授予MathOps_Impl::m_y protected访问权限,而不是private

您明确询问为什么派生类无法访问私有数据。这是设计的。

答案 1 :(得分:0)

您可以通过公共实现类中受保护的成员函数,在不破坏封装的情况下访问公共数据。

无条件的例子如下:)

#include <cstdio>

class Math
{
public:
    virtual ~Math() {}
    virtual int add(int b) const = 0;
};

class MoreMath : public virtual Math
{
public:
    virtual ~MoreMath() {}
    virtual int subtract(int b) const = 0;
};

class MathImpl : public virtual Math
{
private:
    int m_a;

public:
    MathImpl(int a) : m_a(a) {}
    virtual ~MathImpl() {}
    int add(int b) const { return m_a + b; }

protected:
    int value() const { return m_a; }
};

class MoreMathImpl : public virtual MoreMath, private MathImpl
{
public:
    MoreMathImpl(int a) : MathImpl(a) {}
    int subtract(int b) const { return value() - b; }
};

int main()
{
    MoreMath* one = new MoreMathImpl(1);
    printf("1 + 2 = %d\n", one->add(2));
    printf("1 - 2 = %d\n", one->subtract(2));
    delete one;

    return 0;
}