![](/img/trans.png)
[英]Is it possible to enforce constness of passed dependency object in c++
[英]Enforce constness for pointed data in C++?
讓我們有一個帶有一些const和非const方法的Foo
類
struct Foo
{
Foo ();
~Foo();
void noSideEffect() const;
void withSideEffect();
};
我也有一個Bar
類,需要以某種方式引用Foo
。 更確切地說,對於這個問題可能過於精確,Bar實現了運算符||
和&&
為聯合和交叉,所以兩個Bar
實例需要知道他們正在使用同一個Foo
實例 。
我發現最簡單的解決方案是使用指向Foo
對象的指針:
struct Bar
{
Foo * p_foo;
Bar (Foo& foo)
: p_foo(&foo) {};
}
現在兩個bar實例可以一起播放,看看它們是否都處理相同的Foo。 我快樂了。
但現在我想有時使用帶有const Foo
實例的Bar。 好吧,它可能很容易,我只需創建一個const Bar
實例,對吧? 我們去:
const Bar createBarFromConstFoo(const Foo& foo)
{
Foo* newfoo = const_cast<Foo*>(&foo);
const Bar newbar (*newfoo);
return newbar;
}
現在噩夢開始了(請參閱為什么C ++不對指針數據強制執行const? )。 我想我理解為什么 (標准是這樣說的),我的主要問題是如何最好地應對它。
除了這個小標准的東西,createBarFomConstFoo幾乎完成了我想要的東西,因為它返回了一個const Bar
。 有沒有辦法阻止const Bar
使用我的(最初) const Foo
(即只調用Foo的const方法)做一些討厭的事情,同時允許非const Bar執行所有操作?
也許沒有辦法做到這一點,這是一個對象設計問題,但我沒有看到一個簡單的替代方案。
編輯:對於downvoters,你能否解釋一下原因,我可以從你的言論中取得進展......
編輯2 :也許混淆真正的類恐懼Foo和Bar是一個壞主意,我只是想簡化一些事情。
所以Foo
實際上是一種分子(實際上是一種蛋白質),它含有Atoms(許多是蛋白質)。 能夠選擇一些原子是創建Bar的原因,Bar是SelectionOfAtoms
。
有時候從所有氫和氧原子中選擇都是方便的,因此Bar實現了聯合和交叉。 我希望能夠提取這些原子,以便SelectionOfAtoms從所選原子實現createNewMolecule()方法。 因此,它需要一種方法來引用原始分子(也許某種副本會在這里做,但可能不符合下面的其他要求)。
但我最近覺得需要修改選擇的原子,同時保持其他原子不被修改。 通過SelectionOfAtoms(Bar)這么做是很方便的:它已經知道在哪里找到原子(使用指針)和這些原子的索引(內部實現細節),所以改變原子所需的一切幾乎已經在這里,除了我可以要么只在Molecule上使用Selection(非const),要么在const Molecule上工作,忘記修改它們或進入const_cast恐怖。
我敢肯定這是一個非常糟糕的設計,但它已經存在,它肯定會得到很多改進。
使用STL作為指導,將您的分子視為容器,並將您的選擇視為迭代器或迭代器范圍。
現在,在這個方案中,你有const和非const選擇/迭代器的單獨類型 ,這是有道理的,因為它們具有不同的語義。 使constness成為模板參數可能是一種虛假的經濟,除非選擇中的代碼比你建議的多得多。
現在,你從const或非const molecule
,你靜靜地知道你得到了一個const_selection
或(非const) selection
。
它Bar
不是太復雜,你可以把它變成一個類模板。
template <typename FooType>
struct Bar
{
FooType * p_foo;
Bar (FooType& foo)
: p_foo(&foo) {};
}
template <typename FooType>
Bar<FooType> makeBar(FooType& foo)
{
return Bar<FooType>(foo);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.