11

これがあるとしましょう:

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

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

コンパイラはエラーをスローしません。Bも抽象クラスであり、fooAから実装する必要がないためだと思います。しかし、そのような構造はどういう意味ですか?

1)fooBからはAから隠れfooますか?

2)Bを継承し、抽象クラスではない最初のクラスは、次のような2つの実装を提供する必要がありますか。

class C: public B
{
   public:
   virtual void A::foo() {};
   virtual void B::foo() {};
};

コンパイラは、の実装が欠落している場合にのみ文句を言いますが、の実装B::foo()が欠落していることについては文句を言いませんA::foo()

全体として:これは純粋仮想メソッドを隠す方法ですか?

4

3 に答える 3

14

最初に宣言するとき:

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

fooメソッドをpublic、virtual、pureと宣言しています。クラスに少なくとも純粋メソッドが含まれている場合、それは抽象と呼ばれます。どういう意味ですか?これは、純粋なメソッドの実装が必要なため、クラスをインスタンス化できないことを意味します。

あなたは明らかに抽象クラスから継承することができます(私はあなたがそれをしなければならないと言うでしょう、そうでなければあなたが継承するためのインターフェースを提供することを除いてあなたが使っていない抽象クラスの必要性は何でしょうか?)そしてあなたはまたすることができます抽象クラスから継承し、親クラスの純粋なメソッドの一部またはすべてを実装しない。この場合、子クラスも抽象的です。これは、クラスBの場合です。

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

virtual void foo() = 0;Bでは、定義がすでに基本クラスから継承されているため、宣言を簡単に省略できます。この場合、クラスBは抽象クラスであるため、Aのようにインスタンス化することはできません。

質問に直接答えるには:

BからはAfooから隠れますか?foo

いいえ、違います。どちらも純粋メソッド(実際には同じメソッド)を宣言しているため、実際に隠すものはありません。

Bを継承し、抽象クラスではない最初のクラスは、提供されているもののように2つの実装を提供する必要がありますか?

いいえ、もちろん違います。上記のように、これらは同じメソッドであるため、クラスCが実装を提供する必要がある場合は、次のように実装fooする必要がありますfoo

class C: public B
{
   public:
   virtual void foo() {};
};
于 2013-03-24T21:00:24.307 に答える
8

0)コンパイラはエラーをスローしません...

オブジェクトをインスタンス化しようとすると、AまたはオブジェクトBが抽象化されている場合、エラーがスローされます。それらを継承して宣言しているときではありません。

 

1)BのfooはAのfooを隠しますか?

いいえ、それはそれA::fooを隠しません。

 

2)Bを継承し、抽象クラスではない最初のクラスは、2つの実装を提供する必要がありますか...

いいえ。オーバーライドfooして、1つの実装を作成するだけです。

 

class C : public B
{
public:
    virtual void foo()
    {
        std::cout << "ABCD" << std::endl;
    }
};


int main()
{
    C c;
    A *a = &c;
    a->foo(); //  Prints ABCD string and proofs B::foo doesn't hide A::foo
}
于 2013-03-24T20:29:13.183 に答える
1

コードをgcc4.5.3でコンパイルしたところ、次のエラーメッセージが表示されました。

error: cannot define member function ‘A::foo’ within ‘C’
error: cannot define member function 'B::foo' within 'C'

あなたの例では、fooは純粋な仮想であるため、クラスAとは両方とも抽象クラスです。これらは、使用するデフォルトの動作がないため(派生クラスが抽象化されていない場合)、BBの派生クラスがの動作を実装する必要があることを定義するだけです。foo

Question 1:Does foo from B hide foo from A?

fooとはまったく同じ名前BであるためA、同じシグニチャとfooは基本クラスで仮想であり、非表示ではなく、オーバーライドされます。参考:署名が同じで、基本クラスで仮想として宣言されている場合、派生クラスの関数overridesは基本クラス関数です。基本クラスへのポインタまたは参照を介して呼び出すと、派生クラスの関数が呼び出されます。基本クラスのものを「オーバーライド」します。 Hidingポインタまたは参照を介して、または派生クラスのオブジェクトを使用して直接非仮想関数を呼び出す場合にのみ機能します。派生クラスの関数は、同じ名前のすべての基本クラス関数を非表示にします。

Question 2: The first class which inherits from B and is not an abstract class, does it have to provide two implementations

いいえ。次のことができます。

  class C: public B
  {
   public:
      virtual void foo()
      {
        cout << "foo defined in c" <<endl;
      }
 };
于 2013-03-24T20:53:23.447 に答える