在C++中为尖头数据强制执行const?

asc*_*bol 5 c++ oop pointers const

让一个Foo类包含一些const和非const方法

struct Foo
{
    Foo ();
    ~Foo();

    void noSideEffect() const;
    void withSideEffect();

};
Run Code Online (Sandbox Code Playgroud)

我也有一个Bar类,需要以Foo某种方式引用.更确切地说,对于这个问题可能过于精确,Bar实现了运算符||以及&&联合和交集,因此两个Bar实例需要知道它们是在同一个实例上运行的Foo.

我找到的最简单的解决方案是使用指向Foo对象的指针:

struct Bar
{

   Foo * p_foo;

   Bar (Foo& foo)
     : p_foo(&foo) {};

}
Run Code Online (Sandbox Code Playgroud)

现在两个bar实例可以一起播放,看看它们是否都处理相同的Foo.我快乐了.

但是现在我想有时使用Bar和const Foo实例.嗯,这可能很容易,我只需创建一个const Bar实例,对吧?我们去:

const Bar createBarFromConstFoo(const Foo& foo)
{
   Foo* newfoo = const_cast<Foo*>(&foo);
   const Bar newbar (*newfoo);
   return newbar;
}
Run Code Online (Sandbox Code Playgroud)

现在噩梦开始了(请参阅为什么C++不对指针数据强制执行const?).我想我理解为什么(标准是这样说的),我的主要问题是如何最好地应对它.

除了这个小标准的东西,createBarFomConstFoo几乎完成了我想要的东西,因为它返回了一个const Bar.有没有办法防止一个const Bar令人讨厌的东西用我的(最初)const Foo(即只调用Foo的const方法),同时允许非const Bar做所有事情?

也许没有办法做到这一点,这是一个对象设计问题,但我没有看到一个简单的替代方案.

编辑:对于downvoters,你能否解释一下原因,我可以从你的言论中取得进展......

编辑2:也许混淆真正的类恐惧Foo和Bar是一个坏主意,我只是想简化一些事情.

所以,Foo事实上是一个分子(事实上的蛋白),其中包含原子(多为蛋白质).能够选择一些原子是创建Bar的原因,这是一个SelectionOfAtoms.

有时候从所有氢和氧原子中选择都是方便的,因此Bar实现了联合和交叉.我希望能够提取这些原子,以便SelectionOfAtoms从所选原子实现createNewMolecule()方法.因此,它需要一种方法来引用原始分子(也许某种副本会在这里做,但可能不符合下面的其他要求).

但我最近觉得有必要修改选择的原子,同时保持其他原子不被修改.通过SelectionOfAtoms(Bar)这么做是很方便的:它已经知道在哪里找到原子(使用指针)和这些原子的索引(内部实现细节),所以改变原子所需的一切几乎已经在这里,除了我可以要么只在Molecule上使用Selection(非const),要么在const Molecule上工作,忘记修改它们或进入const_cast恐怖.

我敢肯定这是一个非常糟糕的设计,但它已经存在,它肯定会得到很大改善.

Use*_*ess 3

使用 STL 作为指导,将分子视为容器,将选择视为迭代器或迭代器范围之类的东西。

现在,在这个方案中,您将拥有针对 const 和非常量选择/迭代器的单独类型,这是有意义的,因为它们具有不同的语义。将常量作为模板参数可能是错误的经济做法,除非选择的代码比您建议的多得多。

现在,您从 const 或 non-const 开始molecule,并且静态地知道您将得到 ether aconst_selection或 (non-const) selection