3

クラス foo はインターフェイスとして機能し、純粋な仮想関数を持ち、派生クラスがすべての実装でそれらを提供する必要がないように、便宜上同じ名前のパブリック オーバーロード関数も提供します。

ただし、派生クラスは純粋仮想関数をオーバーライドする必要があるため、foo の public 関数を隠します。
「using foo::A」で試しましたが、「using」はプライベート関数を含むすべての関数をもたらし、コンパイラ エラー「エラー C2876: 'foo' : not all overloads areaccessible」になるため、機能しません。

class foo
{
private:
    virtual void A(int a)=0;
public:
    void A()
    {
        A(1000);
    }
    void A(int a, int b)
    {
        A(a+b);
    }

};

class bar : public foo
{
private:
    virtual void A(int a)
    {
        cout << a << "\n";
    }

};

int main()
{
    bar x;
    x.A();
    return 0;
}

foo から派生したすべてのクラスでオーバーロードされたすべての関数を再定義できることはわかっていますが、これは利便性の目的に反します。
または、A() を呼び出す前に bar を foo にキャストできますが、どの関数がどのクラスで定義されているかを覚えておく必要があるため、このアプローチは混乱します。例えば:

class foo
{
private:
    virtual void A(int a)=0;
public:
    void A()
    {
        A(1000);
    }
    void A(int a, int b)
    {
        A(a+b);
    }
};

class bar : public foo
{
private:
    virtual void A(int a)
    {
        cout << "bar:" << a << "\n";
    }
public:
    void A(int a, int b, int c)
    {
        A(a+b+c);
    }
};

class foobar : public bar
{
private:
    virtual void A(int a)
    {
        cout << "foobar:" << a << "\n";
    }
};

int main()
{
    foobar x;
    x.foo::A();
    x.bar::A(1,2,3);
    return 0;
}

引数のない A は foo に由来し、引数が 3 つある A は bar に由来することを明確に覚えておく必要があります。これも利便性が悪い。

4

1 に答える 1

3

非仮想インターフェイスのイディオムを使用する場合は、2 つの関数 (パブリック非仮想とプライベート仮想) に異なる名前を付ける方が安全で、より明示的です。

これは、コードが何をするかをよく示しており、問題を解決します:

class foo
{
private:
    virtual void doA(int a)=0;
public:
    void A()
    {
        doA(1000);
    }
    void A(int a, int b)
    {
        doA(a+b);
    }

};

もちろん、階層を変更することも忘れないでください。

于 2013-05-23T08:58:11.737 に答える