1. ホーム
  2. c++

[解決済み] publicなconstメソッドがprivateな時に呼び出されないのはなぜですか?

2022-08-14 18:36:40

質問

このコードを考えてみましょう。

struct A
{
    void foo() const
    {
        std::cout << "const" << std::endl;
    }

    private:

        void foo()
        {
            std::cout << "non - const" << std::endl;
        }
};

int main()
{
    A a;
    a.foo();
}

コンパイラのエラーは

error: 'void A::foo()' is private`.

しかし、privateの方を削除するとそのまま動作してしまいます。なぜconstでない方はprivateなのにpublicのconstメソッドは呼ばれないのでしょうか?

つまり、なぜアクセス制御よりもオーバーロードの解決が優先されるのでしょうか?これは不思議です。一貫性があると思いますか?私のコードは動作し、その後、私はメソッドを追加し、私の作業コードはまったくコンパイルされません。

どのように解決するのですか?

を呼び出すと a.foo(); を呼び出すと、コンパイラはオーバーロードの解決を行い、使用するのに最適な関数を見つけます。オーバーロードのセットを構築するとき、コンパイラは

void foo() const

void foo()

さて、このように aconst でない場合、非構成バージョンの方が最適であるため、コンパイラは void foo() . そして、アクセス制限をかけると、コンパイラーエラーが発生します。 void foo() はプライベートであるため、コンパイラエラーが発生します。

覚えておいてほしいのは、過負荷解消では「最も使える関数を探す」のではないということです。最適な関数を見つけ、それを使用しようとする」のです。アクセス制限や削除されたために使用できない場合は、コンパイラーエラーが発生します。

言い換えれば、なぜアクセス制御よりもオーバーロードの解決が先なのか?

さて、見てみましょう。

struct Base
{
    void foo() { std::cout << "Base\n"; }
};

struct Derived : Base
{
    void foo() { std::cout << "Derived\n"; }
};

struct Foo
{
    void foo(Base * b) { b->foo(); }
private:
    void foo(Derived * d) { d->foo(); }
};

int main()
{
    Derived d;
    Foo f;
    f.foo(&d);
}

ここで、私が実際に作るつもりではなかったとしましょう。 void foo(Derived * d) をプライベートなものにするつもりはなかったとしましょう。もしアクセス制御が優先されるなら、このプログラムはコンパイルされ、実行されて Base と表示されるでしょう。これは大規模なコードベースにおいて追跡するのが非常に困難です。アクセス制御がオーバーロードの解決の後に来るので、私が呼び出したい関数が呼び出されないことを伝える素晴らしいコンパイラー エラーが得られ、バグをより簡単に発見することができます。