C++ 友谊不是继承的——还有什么选择?
我已经写了/正在写一段物理分析代码,最初是为我自己写的,现在希望能被一小群物理学家使用和扩展。我们当中没有一个是C++大师。我已经建立了一个小框架,它将“物理事件”数据抽象为由一系列工具作用的对象,这些工具可以根据分析需求轻松地进行交换 这为代码创建了两个部分:“物理分析”代码,该代码操纵事件对象,并通过基本“工具”的派生生成结果;“结构化”代码附加输入文件,将作业拆分为并行运行,根据脚本将工具链接成链,等等 问题在于:对于其他人来说,为了使用代码,每个用户都必须能够遵循以任何方式修改事件数据的每个步骤。因此,(许多)额外的困难结构代码行可能会让人望而生畏,除非它明显地和物理无关。更糟糕的是,过多的细节可能会让人们产生想法——我宁愿他们没有很好的理由也不要编辑结构代码——最重要的是,他们不能引入任何影响物理的东西 我希望能够:C++ 友谊不是继承的——还有什么选择?,c++,inheritance,physics,analysis,friend,C++,Inheritance,Physics,Analysis,Friend,我已经写了/正在写一段物理分析代码,最初是为我自己写的,现在希望能被一小群物理学家使用和扩展。我们当中没有一个是C++大师。我已经建立了一个小框架,它将“物理事件”数据抽象为由一系列工具作用的对象,这些工具可以根据分析需求轻松地进行交换 这为代码创建了两个部分:“物理分析”代码,该代码操纵事件对象,并通过基本“工具”的派生生成结果;“结构化”代码附加输入文件,将作业拆分为并行运行,根据脚本将工具链接成链,等等 问题在于:对于其他人来说,为了使用代码,每个用户都必须能够遵循以任何方式修改事件数据的
- A) 以明显的方式证明 结构代码不编辑结构 任何方式的事件数据
- B) 一旦其他用户使用,就强制执行此操作 开始扩展代码本身 (我们都不是 专家,物理总是来的 第一个翻译:任何东西都不是 对一个讨厌的人来说,用螺栓固定是公平的游戏 (黑客)
为了澄清这种情况,我有以下几点
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可见性
#错误“有人将工具实现细节泄漏到结构代码中”
#恩迪夫
...
请注意,这种分区有助于将工具和结构代码放在不同的库中—您甚至可以限制对结构代码的访问