定数版と非常量版のメンバー関数
時間:2014.03.15
場所:基地
----------------------------------------------------------------
一、使用原則
場所:基地
----------------------------------------------------------------
一、使用原則
メンバー関数の戻り値がタイプを指すポインタまたは参照である場合、通常は2つのバージョンのメンバー関数を提供します.定数版はconst Type*またはconst Type&を返し、通常版は通常のポインタまたは参照を返します.定数版から返されるポインタまたは参照は、定数オブジェクトを指します.オブジェクトを変更するために依存することはできません.通常版は、オブジェクトを変更するために通常のポインタまたは参照を返します.
----------------------------------------------------------------
二、なぜそうするのかとそのメリット
クラスを実装する場合、チェーンテーブルでは、リンクドメインのコピーを取得する必要があります.これは、リンクドメインを変更しないため、定数メンバー関数によって取得されます.次のようにします.node* link() const {return link_field;}
このようにコンパイルは成功するが、このように定数メンバー関数のプログラミングテクニックと衝突することを実現するには、定数メンバー関数の目的はオブジェクトデータの修正を防止することであることを知っているが、ここでは、定数メンバー関数であるにもかかわらず、戻り結果は通常のポインタであり、ポインタを修正することでデータを修正することができる.これは,定数メンバー関数の結果を用いてデータ情報を修正することはできないというプログラミングの原則に触れている.このように、メンバー関数で得られたポインタや参照で修正目的を達成したい場合は、定数メンバー関数を使わずに、この需要を一般化します.node* link() {return link_field;}
これにより、この一般版のメンバー関数でポインタを取得して関連情報を変更できるようにする設計意図が明確になります.
しかし、このようにするとまた問題があります.あなたのノードが定数ノードであると仮定すると、const node*cは、定数メンバーのみを呼び出すことができ、上記の実装ではc->link()を呼び出すことはできません.この問題を解決する方法は、定数版のlink()メンバー関数を提供することです.次のようになります.const node* link() const{return link_field;}
するとc->link()を使うことができます.
通常版と定数版の実装の関数体部分は同じで、link_を返します.fieldですが、定数版ではコンパイラがlink_fieldのタイプはconst node*に変換され、このような戻り値でデータ情報を変更することはできません.
----------------------------------------------------------------
三、設計構想の総括
まず、このようなクラスが必要ですが、特定のオブジェクトは通常のオブジェクトでも定数のオブジェクトでもあり、定数のオブジェクトでは定数メンバー関数しか呼び出せませんが、このように実装されています.node* link() const {return link_field;}
この関数によって返される値は依然としてデータを修正することができ、私たちが望んでいないように、私たちはこのようにする必要があります.const node* link() const{return link_field;}
これは定数ポインタを返します.これで安全ですが、通常のオブジェクトであれば、データを変更するために通常のポインタを返したい場合は、このようにする必要があります.node* link() {return link_field;}
通常のポインタに戻して目的を達成します.
つまり、オブジェクトには通常オブジェクトと定数オブジェクトの区別があるので、返されるポインタ(参照)にも通常ポインタ(参照)と定数ポインタ(参照)の区別が必要です.また、定数オブジェクトは定数メンバー関数しか呼び出せないため、定数メンバー関数として実現されますが、通常オブジェクトが呼び出す関数については、関数定数はどうでもいいですが、定数であることが望ましいです.あなたの明確な設計意図を表現します.
二、なぜそうするのかとそのメリット
クラスを実装する場合、チェーンテーブルでは、リンクドメインのコピーを取得する必要があります.これは、リンクドメインを変更しないため、定数メンバー関数によって取得されます.次のようにします.node* link() const {return link_field;}
このようにコンパイルは成功するが、このように定数メンバー関数のプログラミングテクニックと衝突することを実現するには、定数メンバー関数の目的はオブジェクトデータの修正を防止することであることを知っているが、ここでは、定数メンバー関数であるにもかかわらず、戻り結果は通常のポインタであり、ポインタを修正することでデータを修正することができる.これは,定数メンバー関数の結果を用いてデータ情報を修正することはできないというプログラミングの原則に触れている.このように、メンバー関数で得られたポインタや参照で修正目的を達成したい場合は、定数メンバー関数を使わずに、この需要を一般化します.node* link() {return link_field;}
これにより、この一般版のメンバー関数でポインタを取得して関連情報を変更できるようにする設計意図が明確になります.
しかし、このようにするとまた問題があります.あなたのノードが定数ノードであると仮定すると、const node*cは、定数メンバーのみを呼び出すことができ、上記の実装ではc->link()を呼び出すことはできません.この問題を解決する方法は、定数版のlink()メンバー関数を提供することです.次のようになります.const node* link() const{return link_field;}
するとc->link()を使うことができます.
通常版と定数版の実装の関数体部分は同じで、link_を返します.fieldですが、定数版ではコンパイラがlink_fieldのタイプはconst node*に変換され、このような戻り値でデータ情報を変更することはできません.
----------------------------------------------------------------
三、設計構想の総括
まず、このようなクラスが必要ですが、特定のオブジェクトは通常のオブジェクトでも定数のオブジェクトでもあり、定数のオブジェクトでは定数メンバー関数しか呼び出せませんが、このように実装されています.node* link() const {return link_field;}
この関数によって返される値は依然としてデータを修正することができ、私たちが望んでいないように、私たちはこのようにする必要があります.const node* link() const{return link_field;}
これは定数ポインタを返します.これで安全ですが、通常のオブジェクトであれば、データを変更するために通常のポインタを返したい場合は、このようにする必要があります.node* link() {return link_field;}
通常のポインタに戻して目的を達成します.
つまり、オブジェクトには通常オブジェクトと定数オブジェクトの区別があるので、返されるポインタ(参照)にも通常ポインタ(参照)と定数ポインタ(参照)の区別が必要です.また、定数オブジェクトは定数メンバー関数しか呼び出せないため、定数メンバー関数として実現されますが、通常オブジェクトが呼び出す関数については、関数定数はどうでもいいですが、定数であることが望ましいです.あなたの明確な設計意図を表現します.
node* link() const {return link_field;}
node* link() {return link_field;}
const node* link() const{return link_field;}
三、設計構想の総括
まず、このようなクラスが必要ですが、特定のオブジェクトは通常のオブジェクトでも定数のオブジェクトでもあり、定数のオブジェクトでは定数メンバー関数しか呼び出せませんが、このように実装されています.node* link() const {return link_field;}
この関数によって返される値は依然としてデータを修正することができ、私たちが望んでいないように、私たちはこのようにする必要があります.const node* link() const{return link_field;}
これは定数ポインタを返します.これで安全ですが、通常のオブジェクトであれば、データを変更するために通常のポインタを返したい場合は、このようにする必要があります.node* link() {return link_field;}
通常のポインタに戻して目的を達成します.
つまり、オブジェクトには通常オブジェクトと定数オブジェクトの区別があるので、返されるポインタ(参照)にも通常ポインタ(参照)と定数ポインタ(参照)の区別が必要です.また、定数オブジェクトは定数メンバー関数しか呼び出せないため、定数メンバー関数として実現されますが、通常オブジェクトが呼び出す関数については、関数定数はどうでもいいですが、定数であることが望ましいです.あなたの明確な設計意図を表現します.
node* link() const {return link_field;}
const node* link() const{return link_field;}
node* link() {return link_field;}