C++:处理这种多重继承的最佳方法是什么
C++: what is the best way to handle this multi-inheritance?
页面基本上是一个固定大小的类型数组,但它提供了其他对这个问题不重要的功能。具体来说,每个页面都有一个recordOffset
,这意味着该页面的记录ID是连续的,并从该索引开始(页面可以被视为较大阵列的离散任意段)
class AbstractPage
{
protected:
unsigned int recordOffset;
public:
AbstractPage(unsigned int recordOffset);
virtual ~AbstractPage();
// a mixture of pure and non-pure virtual functions
virtual string toString() const;
virtual unsigned int getCount() const = 0;
virtual PageType pageType() const = 0;
};
class IntegerPage : public AbstractPage
{
public:
vector<int> data;
IntegerPage(const vector<int>& data);
virtual ~IntegerPage();
// our concrete implementation
virtual unsigned int getCount() const;
virtual PageType pageType() const;
};
class FloatPage : public AbstractPage
{
public:
vector<float> data;
FloatPage(const vector<float>& data);
virtual ~FloatPage();
// our concrete implementation
virtual unsigned int getCount() const;
virtual PageType pageType() const;
};
我不想为此使用模板,因为这些页面被这样使用;
LinkedList<AbstractPage> pages;
在大多数情况下,我将使用AbstractPage
提供的接口方法与页面进行交互。当我需要直接读/写数据时,我会单独知道类型并使用:
dynamic_cast<FloatPage>(abstractPage).data[0] = 12.34;
到目前为止还不错,但这是一个进退两难的问题;我需要扩展每种类型来创建页面的索引版本:
class AbstractIndexedPage
{
public:
// this is instead of the recordOffset of AbstractPage
vector<unsigned int> recordIds;
};
class IndexedIntegerPage : public AbstractIndexedPage, public IntegerPage
{
};
现在我想能够做到这一点:
AbstractIndexedPage sort(const AbstractPage& page)
{
// Sorting will swap around the data and therefore we need to keep track of the
// record IDs in an Indexed page.
// If the incoming concrete type is IntegerPage, the output will be
// IndexedIntegerPage
}
问题是返回的对象将没有到AbstractPage
:的接口
AbstractIndexedPage sortedPage = sort(originalPage);
sortedPage.getCount(); // can't do this!
dynamic_cast<AbstractPage>(sortedPage).getCount() // can do this, but pretty messy
根据我所读到的,除了select之外,所有情况下的多重继承都意味着你的代码基本上设计得很糟糕。在这种情况下,有来自两个非接口的多重继承,这两个类都将有一个构造函数(和虚拟析构函数),但只能直接处理它们提供的实例变量。
我的选择是:
AbstractIndexedPage
扩展了AbstractPage
并使用virtual
继承,因为现在将有两个AbstractPage
。但这将给我完整的界面。但这不是一个顽皮的黑客吗- 只需在
IndexedIntegerPage
和IntegerPage
中复制data
或recordIds
实例变量,即可在不需要继承的情况下提供相同的功能 - 以不同的方式设计架构
感谢
您可以使用委派来完成这项工作。例如,在AbstractIndexedPage
:
class AbstractIndexedPage
{
public:
// this is instead of the recordOffset of AbstractPage
vector<unsigned int> recordIds;
AbstractClass* getPage() { return page;};
private:
AbstractClass *page;
};
做一些类似的事情:
AbstractIndexedPage sortedPage = sort(originalPage);
sortedPage.getPage()->getCount(); // can't do this!
当然,要核实所有可能的错误或解释。
附言:有人会告诉你使用智能指针,我会同意他们的意见,但为了简单起见,我只使用普通指针
我本来打算在评论中发布这篇文章,但代码看起来很糟糕。您可以考虑在较低级别进行抽象:创建一个AnyType
,并在此基础上创建一个页面类型:
union AnyType {
float f;
int i;
};
class AnyPage : public AbstractPage
{
public:
enum PageDataType {FloatPage, IntPage};
vector<AnyType> data;
AnyPage(const vector<int>& data); //creates an 'IntPage'
AnyPage(const vector<float>& data); //creates a 'FloatPage'
virtual ~AnyPage();
// our concrete implementation
virtual unsigned int getCount() const;
virtual PageType pageType() const;
private:
PageDataType myType;
};
然后你可以创建AnyPage
的链接列表,正如你所说,当你想访问数据时,你已经知道你要处理的是哪种页面:
anyPage.data[0].f = 12.34;
然后,对于索引品种,它不再是多重继承:
class AnyIndexedPage : public AnyPage
{
public:
// this is instead of the recordOffset of AnyPage
vector<unsigned int> recordIds;
};
相关文章:
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 在C++中向零方向近似的最佳方法
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 检测win32服务创建和删除的最佳方法
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 将线程中的数据存储到全局容器的最佳方法?
- 将一系列整数放入类的最佳方法是什么?
- 在派生类中使用基类的私有成员变量的最佳方法
- 在 C++ 中将非指定类型作为参数传递的最佳方法?
- Qt - QVector 和模型视图 - 从列表视图获取自定义类的最佳方法是什么?
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 比较两个节点坐标的最佳方法是什么?
- 在nodejs中使用本机代码的最佳方法是什么?
- 将 pybind11 绑定标记为已弃用的最佳方法
- C++:将向量传递到构造函数以创建成员变量的最佳方法?
- C++中变量混叠的最佳方法
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?