友谊没有继承 - 有哪些替代方案?

Ant*_*ony 8 c++ inheritance physics analysis friend

我已经写过/我正在编写一段物理分析代码,最初是为了我自己,现在希望由一小群物理学家使用和扩展.我们都不是C++大师.我已经整理了一个小框架,将"物理事件"数据抽象为由一系列工具操作的对象,这些工具可以根据分析要求轻松交换.

这创造了代码的两半:"物理分析"代码,它操纵事件对象并通过基础"工具"的衍生产生我们的结果; 以及附加输入文件的"结构"代码,将作业拆分为并行运行,根据某些脚本将工具链接到链中等.

问题在于:对于其他人来说,要使用代码,每个用户都应该能够遵循以任何方式修改事件数据的每一步.因此,(许多)额外的困难结构代码线可能是令人生畏的,除非它明显且明显地是物理学的外围.更糟糕的是,在太多细节上看它可能会给人们一些想法 - 我宁愿他们没有很好的理由不编辑结构代码 - 最重要的是他们不得引入任何影响物理的东西.

我希望能够:

  • A)以明显的方式演示结构代码不以任何方式编辑事件数据
  • B)一旦其他用户开始自己扩展代码就强制执行(我们都不是专家,物理总是第一位 - 翻译:任何没有用的东西都是公平的游戏,讨厌讨厌的黑客)

在我理想的场景中,事件数据将是私有的,派生的物理工具继承了Tool基类的访问权限.当然,实际上这是不允许的.我听说有充分的理由,但这不是问题.

不幸的是,在这种情况下,从基础(它是朋友)调用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
        }
};
Run Code Online (Sandbox Code Playgroud)

由于上述两个原因(A和B),理想情况是将对Event的内容的访问限制为仅这些工具.

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

Dav*_*eas 2

C++ 中存在三个访问限定符:publicprotectedprivate带有从 Tool 基类继承访问权限的派生物理工具的句子似乎表明您想要protected访问,但尚不清楚实际数据是否位于privateTool因此protected足够)或当前private位于 befriends 的类中Tool

在第一种情况下,只需制作数据protected

class Tool {
protected:
   type data;
};
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,您可以尝试在语言上玩一些令人讨厌的把戏,例如在工具级别提供访问器:

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) );      
   }
};
Run Code Online (Sandbox Code Playgroud)

但我会完全避免它。到了某个点,访问说明符就不再有意义了。它们是避免错误的工具,而不是用来监管你的同事,事实是,只要你希望他们编写需要访问该数据(Tool扩展)的代码,你就可能忘记拥有绝对的保护:你不能。

想要访问数据的用户不妨使用新创建的后门来执行此操作:

struct Evil : Tool {
   static type& break_rule( Data & d ) {
      return gain_access_to_data( d );
   }
};
Run Code Online (Sandbox Code Playgroud)

而现在每个人都可以简单地Evil作为一扇门来使用Data。我建议您阅读C++FAQ-lite以获得有关 C++ 的更多见解。