23

非 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 の別のインスタンスを返す場合があります。

話題をそらしてください。

4

11 に答える 11

15

const_castconstnessをキャストするためのものです!

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

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

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

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

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

const 一時を使用することもオプションです (「MSN」による回答)。

   const Bar* _this = this;
   _this->getProcess().doSomeWork();
于 2009-01-04T15:31:11.577 に答える
10

キャストを避けてください。 this を a などに割り当て、const Bar *それを使用して を呼び出しますgetProcess()

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

于 2009-01-02T19:10:53.550 に答える
5

キャストが醜い場合は、代わりに、次Barのconst参照を返すメソッドを追加でき*thisます。

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

次に、先頭に追加するだけで任意の constメソッドを呼び出すことができます。例:Baras_const().

as_const().getProcess().doSomeWork();
于 2009-01-09T08:00:42.840 に答える
4

とが同じオブジェクトへの参照getProcess()getProcess() const返さない (ただし修飾が異なる) 場合は、 の設計が不適切であることを示していclass Barます。関数の性質をオーバーロードすることconstは、異なる動作を持つ関数を区別する良い方法ではありません。

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

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

getProcess().doSomeWork();

まったく同じdoSomeWork()関数を呼び出すので、const_cast.

于 2009-01-02T15:42:59.197 に答える
1

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

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

編集:質問全体を読んでいません。はい、thisポインターを const_cast するか、doOtherWork関数を const にしてconst IProcess& getProcess() constを呼び出す必要があります。

doSomeWorkを呼び出すために const オブジェクトが必要ないという点はそのままです。それが目的なので、const メソッドを呼び出す必要はありますか?

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

于 2009-01-02T15:31:38.970 に答える
1

テンプレートを定義する

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

そして電話する

addConst( getProcess() ).doSomeWork();
于 2012-12-06T10:35:17.337 に答える
0

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

const IProcess* getProcessConst() const { return ... }
...
getProcessConst().doSomeWork();
于 2009-01-02T15:41:31.103 に答える
0

const オブジェクトから呼び出されたかどうかに応じて、DoOtherWork が 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     
  }
};

それがうまくいったとしても、これは私には悪臭のように見えます. オブジェクトの constness に応じて、クラスの動作が根本的に変化することに非常に警戒します。

于 2009-01-02T15:45:59.377 に答える
0

投稿者 monjardin
別のオプションは、オーバーライドされた関数の名前を変更することです。2 つの関数が実際に異なる動作/副作用を持っている場合、これは非常に良い考えです。それ以外の場合、関数呼び出しの効果は明ら​​かではありません。

IProcess& は、主にプロパティを介して他のコードでアクセスされます

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

そのため、名前を変更することはできませんでした。呼び出し関数の時間定数の大部分はgetProcess() と一致するため、問題はありませんでした。

于 2009-01-02T16:30:57.010 に答える
0

さて、あなたは宣言できますか

void doOtherWork const ()

?

それはそれをするでしょう。

于 2009-01-02T15:32:49.857 に答える
-1

基本的に、他のメソッドまたは const_cast の名前を変更することに行き詰まっています。

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

私が間違っていることを証明し、C++ で使いやすいコピー オン ライト ポインターを示してくれる人を歓迎します...

于 2009-01-02T15:40:44.007 に答える