2013-01-17 29 views
0

我的问题涉及公共和私有继承的组合作为分离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复制。有什么办法可以避免这种复制?

+3

谁愿意适应算术运算成一个层次化的设计? –

+0

再走一步,并拥有一个MathOps_Extn_base?或者把m_y放在MathOps中 – dchhetri

+0

为什么不使用'protected'?但是如果你想用'private'修饰符继承,那么你必须重复它。把'm_y'放在接口中而不把'private'改成'protected'不会有太大的改变。 编辑:关于第一个问题,看看如何在C++中查找名称。如果你把'm_y'作为'Impl0'的保护对象,那么你应该可以在'Impl1'中使用它。 –

回答

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; 
} 
+0

谢谢。我已经接受了你的回答,因为它避免了受保护的成员数据。 – RDK

1

请注意在MathOps_Extn_Impl中复制m_y。有没有办法来 避免这种复制?

是的。给MathOps_Impl::m_yprotected访问而不是private

您明确地问为什么派生类不能访问私人数据。这是设计。

+0

我意识到'private'基类成员的不可访问性。然而,请看我对PiotrJaszkowski的评论,因为我对使用'protected'感到不安。可能是'被保护的'是要走的路,我只是觉得它打破了封装。 – RDK

+0

@RDK我同意你的评论,它可以打破封装。 K-ballo也提出了封装设计异常的有效评论。 –