非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 Bar *
_などに割り当て、それを使用してgetProcess()
を呼び出します。
これを行うにはいくつかの衒学的な理由がありますが、コンパイラに潜在的に危険なことを強制することなく、何をしているのかをより明確にすることもできます。確かに、これらのケースにぶつかることは決してないかもしれませんが、この場合はキャストを使用しないものを書く方がよいでしょう。
const_cast
はキャスト用ですaway constness!
非constから安全なconstにキャストしているので、static_cast
を使用します。
static_cast<const Bar*>(this)->getProcess().doSomeWork();
技術的に言えば、const_cast
で一定にキャストできますが、演算子の実用的な使用法ではありません。 (古いcスタイルのキャストとは対照的に)新しいスタイルのキャストの目的は、キャストの意図を伝えることです。 const_cast
はコードの臭いであり、少なくともその使用法を確認する必要があります。一方、static_cast
は安全です。しかし、それはC++スタイルの問題です。
または、新しい(プライベート)constメソッドを作成し、それをdoOtherWork
から呼び出すことができます。
void doSomeWorkOnProcess() const { getProcess().doSomeWork(); }
Consttemporaryを使用することもオプションです(「MSN」による回答)。
const Bar* _this = this;
_this->getProcess().doSomeWork();
getProcess()
とgetProcess() const
が同じオブジェクトへの参照を返さない(ただし、修飾が異なる)場合は、_class Bar
_の設計が不適切であることを示しています。関数のconst
nessにオーバーロードすることは、動作が異なる関数を区別するための良い方法ではありません。
同じオブジェクトへの参照を返す場合は、次のようにします。
_const_cast<const Bar*>(this)->getProcess().doSomeWork();
_
そして
_getProcess().doSomeWork();
_
まったく同じdoSomeWork()
関数を呼び出すため、_const_cast
_を使用する必要はありません。
キャストが醜い場合は、代わりにBar
にメソッドを追加して、_*this
_へのconst参照を返すことができます。
_Bar const& as_const() const {
return *this; // Compiler adds "const" without needing static_cast<>
}
_
次に、as_const().
を前に付けるだけで、const
でanyBar
メソッドを呼び出すことができます。例:
_as_const().getProcess().doSomeWork();
_
関数がオーバーロードされていない場合は、キャストのトリックを行う必要はありません。非constオブジェクトのconstメソッドを呼び出すことは問題ありません。禁止されているconstオブジェクトからnon-constメソッドを呼び出しています。メソッドがconst関数とnon-const関数でオーバーライドされている場合、オブジェクトをconstにキャストすると、次のトリックが実行されます。
const_cast<const IProcess&> (getProcess()).doSomeWork();
編集:私は質問全体を読んでいませんでした。はい、thisポインターをconst_castするか、doOtherWork関数constを呼び出してconst IProcess&getProcess()constにする必要があります。
重要なのは、doSomeWorkを呼び出すのにconstオブジェクトは必要ないということです。それが目標なので、constメソッドを呼び出す必要がありますか?
別のオプションは、オーバーライドされた関数の名前を変更することです。 2つの関数が実際に異なる動作/副作用を持っている場合、これは本当に良い考えです。そうしないと、関数呼び出しの効果が明確になりません。
テンプレートを定義する
template< class T >
const T & addConst ( T & t )
{
return t;
}
と電話
addConst( getProcess() ).doSomeWork();
投稿者monjardin
別のオプションは、オーバーライドされた関数の名前を変更することです。これは、2つの関数の動作/副作用が実際に異なる場合は非常に良い考えです。そうでない場合、関数呼び出しの効果は明らかではありません。
IProcess&は、主にプロパティを介して他のコードでアクセスされます
__declspec(property(get=getProcess)) IProcess& Process;
そのため、名前を変更することはできませんでした。ほとんどの場合const呼び出し元の関数のネスはgetProcess()と一致するため、問題はありませんでした。
さて、あなたは宣言できますか
void doOtherWork const ()
?
それはそれをするでしょう。
Const_castメソッドが最善の選択肢だと思います。これは、C++のconstフレームワークの制限にすぎません。キャストを回避できる唯一の方法は、constIProcessインスタンスを返すメソッドを定義することだと思います。例えば。
const IProcess* getProcessConst() const { return ... }
...
getProcessConst().doSomeWork();
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
}
};
それがうまくいったとしても、これは私には悪臭のように見えます。オブジェクトの恒常性に応じてクラスの動作が根本的に変化することには非常に注意が必要です。