質問

非 const オブジェクトから const 関数を呼び出す必要があります。例を参照

struct IProcess {
   virtual bool doSomeWork() const = 0L;
};
class Foo : public IProcess {    
  virtual bool doSomeWork() const {
    ...
  }
};

class Bar
{
public:
   const IProcess& getProcess() const {return ...;}
   IProcess& getProcess() {return ...;}

   void doOtherWork {
    getProcess().doSomeWork();        
  }
};

電話をかける

getProcess().doSomeWork();

常に次の呼び出しが行われます

IProcess& getProcess()

別の電話方法はありますか

const IProcess& getProcess() const 

非定数メンバー関数から?これまでに使用した

const_cast<const Bar*>(this)->getProcess().doSomeWork();

これでうまくいきますが、複雑すぎるように思えます。


編集:コードはリファクタリングされており、最終的には 1 つの関数のみが残ることを言及しておきます。

const IProcess& getProcess() const 

ただし、現時点では副作用があり、const 呼び出しが IProcess の別のインスタンスを返す場合があります。

話題を続けてください。

役に立ちましたか?

解決

キャストを回避する:これを constバー* などに割り当て、それを使用して getProcess()を呼び出します。

それを行うためのいくつかの退屈な理由がありますが、潜在的に安全でない何かをコンパイラーに強制することなく、あなたが何をしているのかをより明確にします。確かに、これらのケースをヒットすることはありませんが、このケースではキャストを使用しない何かを書くこともできます。

他のヒント

const_cast は、離れた恒常性をキャストするためのものです!

非constからconstにキャストしているので、 static_cast を使用します:

   static_cast<const Bar*>(this)->getProcess().doSomeWork();

技術的に言えば、 const_cast を使用してconstnessにキャストできますが、これは演算子の実用的な使用ではありません。新しいスタイルのキャストの目的は(古いcスタイルのキャストとは異なり)、キャストの意図を伝えることです。 const_cast はコードのにおいであり、その使用は少なくともレビューする必要があります。一方、 static_cast は安全です。しかし、それはC ++スタイルの問題です。

または、新しい(プライベート)constメソッドを作成し、 doOtherWork から呼び出すことができます:

  void doSomeWorkOnProcess() const { getProcess().doSomeWork(); }

const temporaryの使用もオプションです(&quot; MSN&quot;による回答):

   const Bar* _this = this;
   _this->getProcess().doSomeWork();

getProcess()および getProcess()const が同じオブジェクトへの参照を返さない場合(ただし修飾が異なる場合)は、クラスバー。関数の const nessをオーバーロードすることは、異なる動作を持つ関数を区別する良い方法ではありません。

同じオブジェクトへの参照を返す場合:

const_cast<const Bar*>(this)->getProcess().doSomeWork();

and

getProcess().doSomeWork();

まったく同じ doSomeWork()関数を呼び出すため、 const_cast を使用する必要はありません。

キャストがyouすぎる場合は、代わりに * this へのconst参照を返すメソッドを Bar に追加することができます:

Bar const& as_const() const {
    return *this;    // Compiler adds "const" without needing static_cast<>
}

その後、 as_const()。を追加するだけで、 Bar any const メソッドを呼び出すことができます。例:

as_const().getProcess().doSomeWork();

関数がオーバーロードされていない場合は、キャストのトリックを行う必要はありません。非 const オブジェクトの const メソッドを呼び出しても問題ありません。禁止されている const オブジェクトから非 const メソッドを呼び出しています。メソッドが const 関数および非 const 関数でオーバーライドされている場合は、オブジェクトを const にキャストするとうまくいきます。

const_cast<const IProcess&> (getProcess()).doSomeWork();

編集:質問全体を読んでいませんでした。はい、const_cast する必要があります。 これ ポインターを作成するか、 他の仕事をする 呼び出す関数 const const IProcess& getProcess() const.

重要なのは、呼び出すために const オブジェクトを必要としないということです。 いくつかの作業を行います. 。それが目的なので、 const メソッドを呼び出す必要がありますか?

別のオプションは、オーバーライドされた関数の名前を変更することです。2 つの関数が実際に異なる動作/副作用を持つ場合、これは非常に良いアイデアになります。そうしないと、関数呼び出しの効果が明確になりません。

テンプレートの定義

template< class T >
const T & addConst ( T & t ) 
{
    return t;
}

そして電話

addConst( getProcess() ).doSomeWork();

まあ、宣言できますか

void doOtherWork const ()

それでうまくいきます。

const_castメソッドが最適なオプションだと思います。これは、C ++のconstフレームワークの制限にすぎません。キャストを避けることができる唯一の方法は、const IProcessインスタンスを返すメソッドを定義することだと思います。例えば。

const IProcess* getProcessConst() const { return ... }
...
getProcessConst().doSomeWork();

DoOtherWorkは、constオブジェクトから呼び出されるかどうかに応じて、2つのgetprocess呼び出しのいずれかを呼び出すと仮定します。

提案できる最善の方法は次のとおりです。

class Bar
{
public:
   const IProcess& getProcess() const {return ...;}
   IProcess& getProcess() {return ...;}

   void doOtherWork {            // should use getProcess()      
    getProcess().doSomeWork();        
  }
   void doOtherWork const {
    getProcess().doSomeWork();   // should use getProcess() const     
  }
};

それがうまくいくとしても、これは私にとって悪臭のようです。クラスの振る舞いがオブジェクトの恒常性に応じて根本的に変化するのを非常に警戒します。

投稿者: モンジャルダン
別のオプションは、オーバーライドされた関数の名前を変更することです。2 つの関数が実際に異なる動作/副作用を持つ場合、これは非常に良いアイデアになります。そうしないと、関数呼び出しの効果が明確になりません。

IProcess& には、ほとんどの場合プロパティを通じて他のコードからアクセスします。

__declspec(property(get=getProcess)) IProcess& Process;

したがって、名前を変更するという選択肢はありませんでした。ほとんどの場合 定数呼び出し関数の性質は getProcess() と一致するため、問題はありませんでした。

基本的に、他のメソッドまたはconst_castの名前変更にこだわっています。

ところで、これは、コピーオンライトスマートポインターがC ++で実際にうまく機能しない理由の1つです。コピーオンライトスマートポインターは、無限に共有できるものです。ユーザーが非constコンテキストでデータにアクセスすると、データのコピーが作成されます(ユーザーが一意の参照を保持していない場合)。この種のポインターは、一部のクライアントのみが変更する必要がある大きなデータ構造を共有するときに使用すると非常に便利です。最も「論理的な」実装には、const演算子と非const演算子があります->>。 constバージョンは、基礎となる参照を返すだけです。非constバージョンは、一意の参照チェックとコピーを行います。非constスマートポインターは非const演算子を使用するため、有用ではありません。デフォルトでは、constバージョンを使用する場合でも。 const_castの要件により、非常にユーザーフレンドリーではありません。

私が間違っていることを証明し、C ++でユーザーフレンドリーなコピーオンライトポインターを表示する人を歓迎します...

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top