【发布时间】:2013-01-17 22:24:53
【问题描述】:
我的问题涉及公共继承和私有继承的组合作为在 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_y 在MathOps_Extn_Impl 中的复制。有什么办法可以避免这种复制吗?
【问题讨论】:
-
谁愿意将算术运算融入分层设计?
-
再走一步,拥有一个 MathOps_Extn_base?或者将 m_y 放入 MathOps
-
你为什么不使用
protected?但是,如果您想使用private修饰符进行继承,那么是的,您必须复制它。将m_y放入接口而不将private更改为protected不会有太大变化。编辑:关于第一个问题,看看名称查找在 C++ 中是如何工作的。如果您将m_y置于Impl0中作为保护,那么您应该可以在Impl1中使用它。 -
@PiotrJaszkowski 谢谢。在阅读关于 SO 的其他答案时,我得出了同样的结论(在发布我的问题之前我没有遇到过)。但是,不会让
m_yprotected允许从MathOps_Impl派生的任何(客户端)类直接访问它(并因此破坏封装)? -
@K-ballo 我希望你认真对待你的问题。这是解释我的问题的最小示例。
标签: c++ design-patterns