13

const と non-const の 2 つの get メソッドを持つクラスを作成しました。const メソッドは公開されているため、ユーザーはベクトルを照会できます。非 const メソッドは保護されているため、必要なデータを変更するために使用できます。

ただし、クラスを使用して get メソッドを呼び出そうとすると、コンパイラは非 const メソッドが保護されていると不平を言います。代わりに、const_cast を使用してオブジェクトを const にキャストする必要があるため、代わりに public メソッドを取得できます。

これを解決する方法はありますか?public メソッドがあるのに、なぜコンパイラはキャスト自体を行わないのでしょうか? 保護されたバージョンを削除して const バージョンをそのままにしておくと、正常に動作するため、この状況ではキャストが実行されます。const へのキャストは常に安全です。問題は constness を削除することです。

4

5 に答える 5

7

メンバー アクセス制御は、メンバー関数を呼び出すときに発生する最後の処理です。これは、名前の検索、テンプレート引数の推定、オーバーロードの解決などの後に発生します。これが最後に行われる理由は、メンバーのアクセス制御を変更しても、クライアント コードの実行が突然変更されるべきではないと判断されたためです。

オーバーロードの解決前にアクセスがチェックされ、ライブラリとそのライブラリ内の特定のメンバー関数を使用したとします。次に、ライブラリの作成者は関数を非公開にしました。突然、コードが別のオーバーロードを使用し始め、まったく異なる方法で動作します。ライブラリの作成者はおそらく、関数のオーバーロードを使用しているすべての人が使用を停止することを意図していましたが、全員のコードを変更するつもりはありませんでした。ただし、標準が実際に定義されているため、コードは、動作が異なるのではなく、プライベート メンバーを使用するためのエラーを表示し始めます。

解決策は、保護されたメンバー関数の名前を変更して、考慮されないようにすることです。

于 2012-12-26T18:10:32.513 に答える
5

コンパイラは、呼び出したいメンバー関数を決定した後、アクセシビリティを考慮します。つまり、保護された関数とプライベート関数は、アクセスできなくても表示されます。

なんで?理由の 1 つは、アクセスできない関数をオーバーロードの解決によって無視した場合、アクセシビリティを変更するだけで、呼び出される関数を変更できるからです。現在のルールでは、コンパイル コードをコンパイルに失敗させるか、現在動作しないコードをコンパイルさせるか、コードの意味に影響を与えずに何かを変更することしかできません。アクセス指定子を変更して、暗黙のうちに別の関数を呼び出すことはできません。

不自然な例として、これは非常にひどいクラス インターフェイスです。

public:
    // Returns the amount of change tendered for this transaction.
    MoneyAmount change() const;

private:
    // Account for a change of currency. Charges standard moneychanger's fee.
    MoneyAmount change(Currency toCurrency = Currency::USD);

アクセスできない関数がオーバーロードの解決から削除された場合、クライアント コードは問題なく呼び出すことができますchange()。そして、後で 2 番目のchange(Currency)関数が公開され、最初の関数が削除された場合、そのコードは突然、まったく別の目的で別の関数を黙って呼び出します。現在の規則では、アクセス指定子の変更によってコンパイル プログラムの動作が変更されることはありません。

于 2012-12-26T18:11:58.527 に答える
0

C++ では、メソッドの選択 (オーバーロードの解決) は、パブリック/プライベート アクセス制御を検討する前に行われます。

于 2012-12-26T18:07:54.100 に答える
0

const 以外の getter メソッドの代わりに、保護された setter メソッド (またはデータ メンバー) を使用します。

あなたがs.thを持っていても違いはありません。お気に入り

class A {
    SomeType foo_;
protected:
    SomeType& foo() { return foo_; }

public:
    const SomeType& foo() const { return foo_; }
};

また

class A {
protected:
    SomeType foo_;

public:
    const SomeType& foo() const { return foo_; }
};
于 2012-12-26T18:09:43.787 に答える
0

これは C++ の本来の動作です。呼び出し元がクラスのオブジェクトを非 const である場合、非変換は保護されたものとして定義されます。クラスのオブジェクトを const として定義するか、クラスのオブジェクトで const-cast を使用する必要があります。これにより、メソッドの const バージョンが呼び出されます。

#include <iostream>
class Foo {
    public:
        const void bar() const { std::cout << " const version called\n";}  
    protected:
        void bar() { std::cout << " non const version called\n";}  
};

int main(int argc, char** argv)
{
    const Foo c;
    c.bar(); // -> work

    Foo c1;
    c1.bar(); // compiler complain -> void Foo::bar() is protected
    const_cast<const Foo&>(c1).bar(); // fine 
}
于 2012-12-26T19:03:47.917 に答える