0

このタイトルは何度も使用されていますが、5〜6の例を検索したところ、問題に一致するものが見つかりませんでした。

私は単純な継承の練習をしています。

クラスAは基本クラスであり、クラスBCはそれを継承します。

class A {

};

class B : public A { public:    int i; };

class C : public A { public:    int j; };

そして、次のようなオーバーロードされた関数を含むクラスP:

class P
{
public:
    void change(B *b)
    {
        b->i =1;
    }

    void change(C *c)
    {
        c->j =1;
    }
};

そして、私が次のような関数を使用するとき:

int main()
{
    A *b = new B();
    A *c = new C();
    P p;
    p.change(b);
    p.change(c);
    return 0;
}

次のようなエラーが発生します。

inherit2.cpp: In function ‘int main()’:
inherit2.cpp:37:12: error: call of overloaded ‘change(A*&)’ is ambiguous
inherit2.cpp:37:12: note: candidates are:
inherit2.cpp:21:7: note: void P::change(B*) <near match>
inherit2.cpp:21:7: note:   no known conversion for argument 1 from ‘A*’ to ‘B*’
inherit2.cpp:26:7: note: void P::change(C*) <near match>
inherit2.cpp:26:7: note:   no known conversion for argument 1 from ‘A*’ to ‘C*’
inherit2.cpp:38:12: error: call of overloaded ‘change(A*&)’ is ambiguous
inherit2.cpp:38:12: note: candidates are:
inherit2.cpp:21:7: note: void P::change(B*) <near match>
inherit2.cpp:21:7: note:   no known conversion for argument 1 from ‘A*’ to ‘B*’
inherit2.cpp:26:7: note: void P::change(C*) <near match>
inherit2.cpp:26:7: note:   no known conversion for argument 1 from ‘A*’ to ‘C*’

問題の解決にご協力いただければ幸いです。ラーマン

4

4 に答える 4

2
Polymorphism is one answer

class A
{
public:
    virtual void set() = 0;
};


class B : public A
{
public:
    virtual void set() { i = 1; }
private:
    int i;
};

class C : public A
{
public:
    virtual void set() { j = 1; }
private:
    int j;
};

class P
{
public:
    void change(A *a)
    {
        a->set();
    }
};

int main()
{
    A *b = new B();
    A *c = new C();
    P p;
    p.change(b);
    p.change(c);
    return 0;
}

changeポリモーフィズムでは、複数のメソッドは必要ありません。

于 2012-10-12T10:51:25.860 に答える
2

あなたは出来る:

  • との仮想セッター関数を追加して、ポリモーフィズムを使用しiますj

    class A {
    public:
        virtual void set( int ) = 0;
    };
    
    class B : public A {
    public:
        void set( int value )
        {
            i = value;
        }
    
    private:
        int i;
    };
    
    class C : public A {
    public:
        void set( int value )
        {
            j = value;
        }
    
    private:
        int j;
    };
    
    class P
    {
    public:
        void change(A * obj)
        {
            obj->set(1);
        }
    };
    
    int main()
    {
        A *b = new B();
        A *c = new C();
        P p;
        p.change(b);
        p.change(c);
        return 0;
    }
    
  • ポインターを渡す前に大文字と小文字を区別します。

     A *b = new B();
     A *c = new C();
     P p;
     p.change(static_cast<B*>(b));
     p.change(static_cast<C*>(c));
    
  • change()変数を基本クラスに配置します (そして 2 つの関数を取り除きます)。

    class A {
    public:
        int i;
    };
    
    class B : public A {};
    
    class C : public A {};
    
于 2012-10-12T10:47:17.593 に答える
1

根本的な原因:

change()渡すパラメータを呼び出すと、タイプA *は であり、この関数と完全に一致するクラスはありませんP。コンパイラは可能な限り最適な一致を見つけようとしますが、次の 2 つの選択肢があります。

void change(B *); 
void change(C *);

いずれもA*からB*またはへの変換が必要なため、最適な一致はありませんC*。クラスがこの変換関数を提供していないため、コンパイラがエラーを報告するわけではありません。

解像度:

キャストを使用して、選択する関数のバージョンをコンパイラに正確に伝えます。

p.change(static_cast<B*>(b));  
p.change(static_cast<C*>(c)); 

上記のどちらの場合でも、指しているオブジェクトの実際の型がわかっているため、コンパイラをA *使用してガイドし、最適な一致関数を見つけることができます。static_cast

于 2012-10-12T10:52:16.437 に答える
1

ポリモーフィズムを使用するようにクラス階層を微調整します。

class A
{
public:
    virtual void SetVariable(const int value) = 0;
};

class B : public A
{
public:
    virtual void SetVariable(const int value) override { i = value; }
    int i;
};

class C : public A
{
public:
    virtual void SetVariable(const int value) override { j = value; }
    int j;
};

class P
{
public:
    void change(A *a)
    {
        a->SetVariable(1);
    }
};

Aこのようにして、特定の派生型を知らなくても、基底クラス ( ) へのポインターを使用できます。

于 2012-10-12T10:50:44.723 に答える