9

myTypeポインターであるクラスメンバーmyMemberがあります。constとして宣言されている関数にこのメンバーを割り当てたいと思います。私は次のようにしています:

void func() const
{
     ...
     const_cast<myType*>(myMember) = new myType();
     ...
}

これを行うことはVC++で正常に機能しますが、GCCは「割り当ての左オペランドとして左辺値が必要です」というメッセージでエラーを出します。

メンバーを変更可能にすると、 const_castを削除して値を割り当てるだけで済みます。しかし、それが他の副作用を伴うかどうかは完全にはわかりません。

メンバーを変更可能にすることなく、メンバーを割り当てることはできますか?どのように?メンバーを変更可能にすることで副作用はありますか?

4

5 に答える 5

17

このシナリオ(外部状態に影響を与えないカプセル化された内部状態の変更(結果のキャッシュなど))は、まさにmutableキーワードの目的です。

于 2009-11-25T12:14:42.000 に答える
8

コードは実際にはVC++では機能しません-値を更新していない(または少なくとも更新してはならない)ため、GCCからの警告が表示されます。正しいコードは

const_cast<myType*&>(myMember) = new myType();

または[他の回答から、ありがとう:P]:

const_cast<ThisType*>(this)->myMember = new myType();

効果的に変更可能にするということは、メンバー関数で暗黙const_castのsを取得することを意味します。これは、一般に、でsを大量に実行していることに気付いたときに操作する必要があるものです。それ以外に「可変を使用することによる副作用」はありません。constconst_castthis

この質問をめぐる激しい議論からわかるように、意地悪な使用法mutableと多くのconst_castsは、間違いなくコード内の悪臭の兆候である可能性があります。概念的な観点から、恒常性を捨てたり使用したりするmutableことは、はるかに大きな意味を持つ可能性があります。場合によっては、正しい方法は、メソッドをnon-constに変更することです。つまり、状態を変更しているという事実を把握することです。

それはすべて、コンテキストでのconst-correctnessの重要性によって異なります。mutableピクシーダストのように散らばって作業を行うことは望ましくmutableありませんが、メンバーがオブジェクトの観察可能な状態の一部ではない場合に使用することを目的としています。const-correctnessの最も厳密な見方は、オブジェクトの状態の1ビットを変更できないことを保持します(たとえば、インスタンスがROMにある場合、これは重要かもしれません...)-そのような場合、constnessは必要ありません失われます。また、オブジェクトの外部に外部状態が格納されている場合もあります。たとえば、スレッド固有のキャッシュは、適切かどうかを判断するときに考慮する必要があります。

于 2009-11-25T12:15:51.457 に答える
6

const_castほとんどの場合、設計の失敗の兆候です。あなたの例では、 であってfunc()はならないかconst、 でmyMemberあるべきですmutable

の呼び出し元はfunc()、オブジェクトが変更されないことを期待します。しかし、これは「彼女が気付く方法で変更しない」ことを意味します。これは、その外部状態を変更しないことです。変更myMemberしてもオブジェクトの外部状態が変わらない場合、それがmutableキーワードの目的です。それ以外の場合は、関数の保証を裏切ることになるため、 であってはなりfunc()ません。const

mutableこれは const-correctness を回避するメカニズムではないことに注意してください。それを改善する仕組みです。

于 2009-11-25T12:27:09.937 に答える
5
class Class{
int value;
void func()const{
const_cast<Class*>(this)->value=123;
}
};
于 2009-11-25T12:14:45.760 に答える
1

Steve Gilhamが書いたように、mutableあなたの質問に対する正しい(そして短い)答えです。別の方向へのヒントを与えたいだけです。あなたのシナリオで 1 つ (または複数) のインターフェースを利用することは可能でしょうか? おそらく、次の例から理解できます。

class IRestrictedWriter // may change only some members
{
public:
  virtual void func() = 0; 
}

class MyClass : virtual public IRestrictedWriter
{
public:
  virtual void func()
  {
    mValueToBeWrittenFromEverybody = 123; 
  }

  void otherFunctionNotAccessibleViaIRestrictedWriter()
  {
    mOtherValue1 = 123;
    mOtherValue2 = 345;
  }

  ...   
}

したがって、ある関数に a の代わりに渡すと、 a のIRestrictedReader *代わりにconst MyClass *呼び出すことができるfuncため、変化しますがmValueToBeWrittenFromEverybodymOtherValue1is は一種の「const」です。

. mutable私はいつもちょっとしたハックを見つけます(しかし時々それを使用します)。

于 2009-11-25T12:37:54.737 に答える