简体   繁体   English

C ++:如何对同一数据类使用不同的方法实现?

[英]C++: How can I use different implementation of methods with the same data class?

Background: Various modules of the program I'm involved with deal with the same combination of objects that are grouped together in an aggregating structure. 背景:我所涉及的程序的各个模块处理的是对象的相同组合,这些对象以聚合结构分组在一起。 There are well-known invariants imposed on that combination of objects, and those invariants are respected by all modules to the fullest extent. 对对象的组合施加了众所周知的不变量,所有模块都充分尊重了这些不变量。 Each module is developed by a dedicated team, and each team needs their custom domain-specific methods to deal with that combination of objects. 每个模块都是由专门的团队开发的,每个团队都需要使用其特定于域的自定义方法来处理对象的组合。

Example: To give you a tangible idea, imagine a sequence container class. 示例:为了给您一个切实的想法,请想象一个序列容器类。 The core of the container is the same across all users: it consists of data members for the storage, size/capacity and the allocator. 容器的核心在所有用户中都是相同的:它由用于存储,大小/容量和分配器的数据成员组成。 But the set of methods, the contract and the body of those methods may vary a lot. 但是方法集,合同和这些方法的主体可能相差很大。 One module may implement std-style operations, another module may implement all operations as nothrow methods, yet another module may insist on using their private checked iterators; 一个模块可以实现std风格的操作,另一个模块可以将所有操作实现为nothrow方法,而另一个模块可以坚持使用其私有检查的迭代器; some performance-critical module takes pain to ban all copy operations, while yet another module is all for making copies... Such requirements are well justified in each particular domain of any given module. 一些对性能要求严格的模块要禁止所有复制操作,而另一个模块却只能复制。...这些要求在任何给定模块的每个特定领域中都是合理的。

Speculations: So, providing a single non-redundant set of methods which would satisfy the needs of all the client teams is impossible - requirements of some teams are mutually exclusive. 推测:因此,不可能提供一个可以满足所有客户团队需求的单一非冗余方法集-有些团队的要求是相互排斥的。 Providing only those methods that are commonly required by all modules is rather useless, because the only common part is, probably, the destructor. 只提供所有模块通常需要的那些方法是没有用的,因为唯一的共同部分可能是析构函数。 Throwing together all possible implementations of all methods is not good either: poor maintainability and stability, confusingly bloated interface, lots of name clashes, lots of cross-module dependencies. 将所有方法的所有可能的实现放在一起也不是一件好事:可维护性和稳定性差,接口混乱而,肿,许多名称冲突,许多跨模块依赖性。

The question: What options do I have to let several independent implementations operate on the same set of data members? 问题:要让多个独立的实现对同一组数据成员进行操作,我必须具有哪些选择?

Things I tried: Solutions I can see thus far aren't exactly nice, and I ain't entirely happy with any of them. 我尝试过的事情:到目前为止,我所看到的解决方案并不十分理想,我对其中任何一个都不完全满意。 I'll list them in answers, three approaches one by one. 我将在答案中列出它们,三种方法一一列出。

A possible less-than-perfect solution to my own question: 对于我自己的问题,可能有一种不太理想的解决方案:

1. Don't bother with methods and have freestanding functions instead. 1.不用理会方法,而要拥有独立的功能。

struct CoreData
{
    int   m_x;
    ~CoreData();
};

void TeamA_init(CoreData& data);
void TeamA_push_back(CoreData& data, Whatever args);
Iter TeamA_begin(CoreData& data);

bool TeamB_init(CoreData& data, Other args);
bool TeamB_push_back(CoreData& data, Whatever args);
X* TeamB_begin(CoreData& data);

//---------------------  Usage:
void ServiceOfTeamA::CallServiceOfTeamB(ServiceOfTeamB* srv)
{
    CoreData     d;
    TeamA_init(d);
    srv->Process(&d);
    TeamA_begin(d);
}

void ServiceOfTeamB::Process(CoreData* d)
{
    TeamB_push_back(*d, 567);
}

- What I don't like about this approach is unfriendly syntax, no RAII and all data members being public. -我对这种方法不满意的是语法不友好,没有RAII和所有数据成员都是公开的。 That's C, not C++. 那是C,不是C ++。

+ On the bright side, this approach offers unlimited customization possibilities. +从好的方面来说,这种方法提供了无限的定制可能性。 No restrictions on choosing the right function for the task. 为任务选择正确的功能没有任何限制。 No memory overhead, no runtime overhead (that is technically, the compiler have the same inlining and optimization opportunities as it would have would those free functions be methods). 没有内存开销,没有运行时开销(也就是说,从技术上讲,编译器具有与那些自由函数作为方法相同的内联和优化机会)。

A possible less-than-perfect solution to my own question: 对于我自己的问题,可能有一种不太理想的解决方案:

2. Have a set of classes that operate on an external instance of core data by reference. 2.具有一组通过引用对核心数据的外部实例进行操作的类。

struct CoreData
{
    int   m_x;
    ~CoreData();
};

class TeamA
{
public:
    // Allocates a new instance and owns it.
    TeamA();

    // Attaches an external instance without assuming ownership.
    TeamA(CoreData& ext);

    // Release the core, if must.
    ~TeamA();

    void push_back(Whatever args);
    Iter begin();
    CoreData& GetCore();

private:
    CoreData*     m_core;
    bool               m_doIOwnThatCore;
};

class TeamB
{
public:
    TeamB();
    TeamB(CoreData& ext);
    ~TeamB();

    int push_back(Whatever args);
    CoreData& GetCore();

private:
    CoreData*     m_core;
    bool               m_doIOwnThatCore;
};

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

void ServiceOfTeamB::Process(CoreData* core)
{
    TeamB        d(core);
    d.push_back(567);
}

- What I don't like about this approach is that it imposes slight pessimization in terms of memory usage and performance. -我不喜欢这种方法,因为它在内存使用和性能方面略有悲观。 Also the syntax makes objects of type TeamA and TeamB look like values, while actually they have reference semantic. 语法还使TeamA和TeamB类型的对象看起来像值,而实际上它们具有引用语义。

+ Good news is that this approach allows somewhat better C++ syntax for the calls (but still, there's that ugly GetCore()), and meets RAII. +好消息是,这种方法为调用提供了更好的C ++语法(但仍然有丑陋的GetCore()),并且符合RAII。

A possible less-than-perfect solution to my own question: 对于我自己的问题,可能有一种不太理想的解决方案:

3. Throw the code on the mercy of de-facto defined behavior of reinterpret_cast. 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);
}

- However, such tricks are outlawed by the standard. -但是,这些技巧在标准中是非法的。 So I have to decline this approach, too. 因此,我也必须拒绝这种方法。

+ If it was legal, it would have offered the best syntax of the three, the syntax clearly showing the reference semantic, with RAII and no pessimization. +如果这是合法的,那么它将提供三种语言中最好的语法,该语法清楚地显示了参考语义,并且具有RAII并且没有悲观化。

PS Invalidity of this approach puts me down. PS这种方法的无效性使我失望。 The whole point of layout compatibility seems to give the ability to communicate data between ABI-compatible processes or shared components. 布局兼容性的整个方面似乎都提供了在ABI兼容进程或共享组件之间传递数据的能力。 Too bad it doesn't allow communicating the data between parts of the same application... 太糟糕了,它不允许在同一应用程序的各个部分之间传递数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++如何使用相同的类和方法读取/写入可变大小的数据 - C++ How to use same class and methods for reading/writing variable size data 使用类/结构的不同方法 - C++ - Different methods to use a class/struct - C++ 我可以在C ++中将ftw函数用于类方法吗? - Can I use the ftw-function for class methods in C++? 怎样才能看到C++中不同数据结构的实际实现代码? - How can I see the actual implementation code of different data structures in C++? 如何在C ++中为不同的模板类型使用不同的类定义? (类重载?) - How can I use different definition of class for different template type in C++? (Class Overloading?) C++如何在使用相同的.h时使用相同的.h并选择不同的.cpp? - C++ how can i use the same .h and choose different .cpp when using the same .h? 如何在 C++ 中动态地向类添加方法? - how can I dynamically add methods to a class in c++? 如何使用具有特定方法的类来实例化C ++模板 - How can I instantiate a C++ template with a class with specific methods 我可以在不同的方法中使用相同的互斥锁吗? - Can I use same mutex in different methods? 如何在C ++中的不同类中使用在一个类中定义的结构? - How can I use struct defined in one class in a different class in C++?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM