1

エラーや警告なしでコンパイルされた次のコードがあります。

#include<iostream>

using namespace std;

class Father
{
   public:
   int foo()
   {
       cout<<"int foo";
       return 111;
   }
};
class Son: public Father
{
   public:
   long foo()
   {
       cout<<"long foo";
       return 222;
   }
};

int main()
{
  Son x;
  long n;
  n=x.foo();
  cout<<"\nn is "<<n;
  return 0;
}

出力を以下に示します。

long foo
n is 222

次のプログラムでエラーが発生したため、関数foo()は派生クラスでオーバーライドされ、オーバーロードされなかったと思います。Son

using namespace std;

class Father
{
   public:
   int foo()
   {
       cout<<"int foo";
       return 111;
   }
   long foo()
   {
       cout<<"long foo";
       return 222;
   }
};


int main()
{
  Father x;
  long n;
  n=x.foo();
  cout<<"\nn is "<<n;
}

エラーメッセージを以下に示します。

error: 'long int Father::foo()' cannot be overloaded
error: with 'int Father::foo()'

2 つの関数が戻り値の型だけが異なる場合、オーバーロードではなくオーバーライドが行われるため、両方の結果が期待どおりです。しかし、最初のプログラムのように関数を宣言すると、エラーが発生し、その理由を理解できませんfoo()virtual私が違反したルールは何ですか?プログラムを以下に示します。

#include<iostream>

using namespace std;

class Father
{
   public:
   virtual int foo()
   {
       cout<<"int foo";
       return 111;
   }
};
class Son: public Father
{
   public:
   long foo()
   {
       cout<<"long foo";
       return 222;
   }
};


int main()
{
  Son x;
  long n;
  n=x.foo();
  cout<<"\nn is "<<n;
}

エラーメッセージを以下に示します。

error: conflicting return type specified for 'virtual long int Son::foo()'
error:   overriding 'virtual int Father::foo()'

foo()functionをvirtualclassとして宣言する以外は何も変更していませんFather。すると、最初のプログラムにはなかった衝突が突然発生します。私はこれを理解することができません。

助言がありますか?ありがとうございました。

4

5 に答える 5

3

戻り値の型を変更してオーバーロードすることはできません。関数への引数の型/数を変更する (または const 修飾子を追加するなどの方法で) だけです。派生クラスで実行するとコンパイルされる理由は、派生クラスが本質的に基本クラスからのものを隠すためです。

于 2013-07-05T05:11:48.047 に答える
1

戻り値の型が基本クラスとは異なる仮想関数と派生したものは、標準から許可され、共変関数と呼ばれます。

ただし、戻り値の型にはいくつかの制約が適用されます。基本的に、クラスへのポインターまたは参照を返す場合、共変関数を定義できます。この場合、基本クラスは、その子によって返されるクラスの直接的または間接的な祖先へのポインターまたは参照を返す必要があります。

リファレンスは、たとえばここにあります。

于 2013-07-05T05:34:58.747 に答える
1

メンバー関数が仮想でない場合、派生クラスの同じ名前の関数は、少なくとも通常の意味では、基本クラスの関数をオーバーライドしません。派生クラスの関数は、基本クラスの関数を隠しているだけです。たとえば、次のようなコードがあるとします。

Son s;
Father &f = s;
f.foo();

次に、仮想でない場合ではなくFather::foo()、それが呼び出されます。Son::foo()Father::foo()

Son::foo()はオーバーライドしていないためFather::foo()、戻り値の型が一致するという特別な要件はありません。Father::foo()ただし、 virtualを作成すると、 Son::foo()overrideFather::foo()が実行されるため、戻り値の型に合意が必要です。

さらに、オーバーロードは、戻り値の型が異なるのではなく、引数の型が異なる場合に発生します。戻り値の型のみが異なる同じスコープで宣言された同じ名前の 2 つの関数を持つことは、単純に違法です。

于 2013-07-05T05:12:05.697 に答える