首页 > 解决方案 > C++:如何对同一个数据类使用不同的方法实现?

问题描述

背景: 我参与的程序的各个模块处理相同的对象组合,这些对象组合在一个聚合结构中。对对象组合施加了众所周知的不变量,并且所有模块都最大限度地尊重这些不变量。每个模块都由一个专门的团队开发,每个团队都需要他们自定义的特定于领域的方法来处理对象的组合。

示例: 为了给您一个切实的想法,想象一个序列容器类。容器的核心在所有用户中都是相同的:它由存储、大小/容量和分配器的数据成员组成。但是这些方法的集合、契约和方法体可能会有很大的不同。一个模块可以实现 std 样式的操作,另一个模块可以将所有操作实现为 nothrow 方法,而另一个模块可能坚持使用它们的私有检查迭代器;一些对性能至关重要的模块会痛苦地禁止所有复制操作,而另一个模块则完全用于制作副本……这样的要求在任何给定模块的每个特定领域都是合理的。

推测: 因此,提供一组单一的非冗余方法来满足所有客户团队的需求是不可能的——某些团队的需求是相互排斥的。只提供所有模块通常需要的那些方法是相当无用的,因为唯一的共同部分可能是析构函数。将所有方法的所有可能实现放在一起也不好:可维护性和稳定性差,接口臃肿令人困惑,大量名称冲突,大量跨模块依赖。

问题: 我有哪些选项可以让几个独立的实现对同一组数据成员进行操作?

我尝试过的事情: 到目前为止我能看到的解决方案并不是很好,而且我对其中的任何一个都不完全满意。我将在答案中列出它们,三种方法一一列出。

标签: c++methods

解决方案


我自己的问题的一个可能不太完美的解决方案:

3. 将代码置于 reinterpret_cast 的事实上定义的行为的摆布上。

// This is a standard layout class.
// It is the only class with data members;
// derived classes never append new data members.
class CoreData
{
public:
    // Could be either explicit conversion function
    // or implicit conversion operator.
    template <typename Final>
    // requires <LayoutCompatibleWithCore Final>
    Final& As()
    {
        return reinterpret_cast<Final&>(*this);
    }

protected:
    ~CoreData();

    int      m_x;
};

// No extra data members appended. No extra invariants imposed.
// This class is also a standard layout type,
// fully layout-compatible with CoreData.
class TeamA : public CoreData
{
public:
    void push_back(Whatever args);
    Iter begin();
};

class TeamB : public CoreData
{
public:
    bool push_back(Whatever args);
    X* begin();
};

//---------------------  Usage:
void ServiceOfTeamA::CallServiceOfTeamB(ServiceOfTeamB* srv)
{
    TeamA        d;
    srv->Process(&d);
    d.begin();
}

void ServiceOfTeamB::Process(CoreData* core)
{
    TeamB&       d = core->As<TeamB>();
    d.push_back(567);
}

-但是,标准禁止此类技巧。所以我也不得不拒绝这种方法。

+如果它是合法的,它将提供三者中最好的语法,该语法清楚地显示了引用语义,具有 RAII 并且没有悲观化。

PS这种方法的无效让我失望。布局兼容性的全部意义似乎赋予了在 ABI 兼容进程或共享组件之间进行数据通信的能力。太糟糕了,它不允许在同一应用程序的各个部分之间进行数据通信......


推荐阅读