C++ 友谊不是继承的——还有什么选择?

C++ 友谊不是继承的——还有什么选择?,c++,inheritance,physics,analysis,friend,C++,Inheritance,Physics,Analysis,Friend,我已经写了/正在写一段物理分析代码,最初是为我自己写的,现在希望能被一小群物理学家使用和扩展。我们当中没有一个是C++大师。我已经建立了一个小框架,它将“物理事件”数据抽象为由一系列工具作用的对象,这些工具可以根据分析需求轻松地进行交换 这为代码创建了两个部分:“物理分析”代码,该代码操纵事件对象,并通过基本“工具”的派生生成结果;“结构化”代码附加输入文件,将作业拆分为并行运行,根据脚本将工具链接成链,等等 问题在于:对于其他人来说,为了使用代码,每个用户都必须能够遵循以任何方式修改事件数据的

我已经写了/正在写一段物理分析代码,最初是为我自己写的,现在希望能被一小群物理学家使用和扩展。我们当中没有一个是C++大师。我已经建立了一个小框架,它将“物理事件”数据抽象为由一系列工具作用的对象,这些工具可以根据分析需求轻松地进行交换

这为代码创建了两个部分:“物理分析”代码,该代码操纵事件对象,并通过基本“工具”的派生生成结果;“结构化”代码附加输入文件,将作业拆分为并行运行,根据脚本将工具链接成链,等等

问题在于:对于其他人来说,为了使用代码,每个用户都必须能够遵循以任何方式修改事件数据的每个步骤。因此,(许多)额外的困难结构代码行可能会让人望而生畏,除非它明显地和物理无关。更糟糕的是,过多的细节可能会让人们产生想法——我宁愿他们没有很好的理由也不要编辑结构代码——最重要的是,他们不能引入任何影响物理的东西

我希望能够:

  • A) 以明显的方式证明 结构代码不编辑结构 任何方式的事件数据
  • B) 一旦其他用户使用,就强制执行此操作 开始扩展代码本身 (我们都不是 专家,物理总是来的 第一个翻译:任何东西都不是 对一个讨厌的人来说,用螺栓固定是公平的游戏 (黑客)
在我的理想场景中,事件数据是私有的,派生的物理工具继承了工具基类的访问权限。当然,在现实中这是不允许的。我听说这有很好的理由,但这不是问题所在

不幸的是,在这种情况下,从基(朋友)调用getter/setter的方法会产生比它解决的问题更多的问题——代码应该尽可能干净、易于理解,并且在工具本身的实现中尽可能与物理相连接(用户不需要在C++或程序的内部工作中创建一个工具)。

鉴于我有一个受信任的基类,任何衍生品都将受到密切的审查,是否有其他迂回但经过充分测试的方式只允许访问这些衍生品?或者有任何方式拒绝访问其他一些基类的衍生品


为了澄清这种情况,我有以下几点

class Event
{
    // The event data (particle collections etc)
};

class Tool
{
    public:
        virtual bool apply(Event* ev) = 0;
};

class ExampleTool : public Tool
{
    public:
        bool apply(Event* ev)
        {
            // do something like loop over the electron collection
            // and throw away those will low energy
        }
};
出于上述两个原因(A和B),理想的做法是将对事件内容的访问限制为仅使用这些工具


感谢大家提出的解决方案。我想,正如我所怀疑的,我所希望的完美解决方案是不可能的。dribeas的解决方案在任何其他设置中都是完美的,但正是在apply()函数中,代码需要尽可能清晰简洁,因为我们基本上要花一整天的时间编写/编辑apply()函数,并且还需要理解其他人编写的每一行代码。与其说是关于功能,不如说是关于可读性和工作量。我确实喜欢“无用”中的预处理器解决方案。它并没有真正强制执行分离,但需要有人真正恶意地破坏它。对于那些建议使用库的人,我认为这肯定是一个很好的第一步,但并没有真正解决两个主要问题(因为我仍然需要提供源代码).

C++中有三个访问限定符:
public
protected
private
。派生物理工具从工具基类继承访问权的句子似乎表明您希望
protected
访问,但不清楚
private
的实际数据是否在
工具
(因此
受保护
就足够了)或当前在与
工具
交朋友的类中是
私有的

在第一种情况下,只需将数据
设置为受保护的

class Tool {
protected:
   type data;
};
在第二种情况下,您可以尝试在该语言上玩一些恶作剧,例如,在工具级别提供访问器:

class Data {
   type this_is_private;
   friend class Tool;
};
class Tool {
protected:
   static type& gain_acces_to_data( Data& d ) { 
       return d.this_is_private;
   }
};
class OneTool : public Tool {
public:
   void foo( Data& d ) {
      operate_on( gain_access_to_data(d) );      
   }
};
但我会完全避免这种情况。访问说明符在某一点上失去了意义。它们是避免错误的工具,而不是监督你的同事,事实是只要你想让他们编写需要访问该数据的代码(
Tool
extensions)你最好忘记绝对的保护:你不能

想要访问数据的用户也可以使用新创建的后门:

struct Evil : Tool {
   static type& break_rule( Data & d ) {
      return gain_access_to_data( d );
   }
};

现在大家可以简单地使用<代码>邪恶<代码>作为一个门,来对代码>数据>代码>。我建议你阅读更多关于C++的见解。

也有限制你的可见性而不是访问权限的C风格的方法。它被强制遵守更多的(和某种程度上的)。您的构建系统,而不是语言-尽管您可以使用一种包含保护来防止工具实现细节“意外”泄漏到结构代码中

-- ToolInterface.hpp --
class Event; // just forward declare it

class ToolStructuralInterface
{
    // only what the structural code needs to invoke tools
    virtual void invoke(std::list<Event*> &) = 0;
};

-- ToolImplementation.hpp --
class Event
{
    // only the tool code sees this header
};
// if you really want to prevent accidental inclusion in the structural code
#define TOOL_PRIVATE_VISIBILITY

-- StructuralImplementation.hpp --
...
#ifdef TOOL_PRIVATE_VISIBILITY
#error "someone leaked tool implementation details into the structural code"
#endif
...
--ToolInterface.hpp--
类事件;//只需向前声明它
类工具接口
{
//只有结构代码需要调用的工具
虚拟void调用(std::list&)=0;
};
--ToolImplementation.hpp--
班级活动
{
//只有工具代码可以看到此标题
};
//如果确实要防止意外包含在结构代码中
#定义工具\u私有\u可见性
--http://www.hpp.cn--
...
#ifdef工具\u专用\u可见性
#错误“有人将工具实现细节泄漏到结构代码中”
#恩迪夫
...
请注意,这种分区有助于将工具和结构代码放在不同的库中—您甚至可以限制对结构代码的访问