4

C++ 仮想関数について質問があります。キーワードは、その関数のサブクラス実装がサブクラスごとに異なる可能性があることを通知するために、基本クラスの関数のvirtualC++ 宣言で使用されます。classサブクラスが異なれば、関数の実装も異なる場合があります。

ちょっとわかりません。C++ でインターフェイスを定義すると、今のところ Java とは異なります。

実際、C++ のインターフェイスという言葉の意味がわかりません。virtualヘッダー ファイルのように関数を指定します。次に、基本クラスのサブクラスまたは派生クラスは、仮想関数である限り、任意の方法でそれをオーバーライドできます。

C++ のインターフェイスはヘッダー ファイルですか?

乾杯

4

5 に答える 5

6

Java のインターフェースは、特定の言語構造またはキーワードです。interfaceJava には、Java クラスが実際の実装を提供するのではなく、派生クラスが実装する必要があるインターフェイスを記述することを示すために使用されるキーワードがあります。これは Java コンパイラによってチェックされ、インターフェイスを実装すると主張するクラスがインターフェイスに必要なすべてのメソッドを提供することが保証されます。

Java では、interfaceキーワードは、指定されたインターフェイス クラスによって記述された一連のサービスをクラスが提供することを示します。Java クラスは、複数の異なるインターフェースを実装する場合があります。

C++ の議論でインターフェイスという言葉が使用される方法は、クラス、関数、またはメソッドのパラメーターの型に関係しているため、やや似た概念です。ただしinterface、C++ にはキーワードがありません。インターフェイスという言葉は、「関数インターフェイスは 2 つのショートと 1 つのロングで構成されます」のように、C++ ではより一般的で説明的な方法で使用されます。これは、関数呼び出し引数とその型、関数の呼び出し元と関数本体の間のインターフェイスを示しています。

したがって、C++ のインターフェイスは、インターフェイスを実装するクラスと、クラスからインスタンス化されたオブジェクトを使用するオブジェクトとの間の一種の契約と考えてください。クラスは実際には、それぞれが特定のインターフェースを持ついくつかの異なる関連サービスを提供することもできます。

interfaceクラス記述で純粋仮想メソッドを使用して抽象クラスを作成することにより、C++ での Java の概念に似たことができます。これにより、実装のない C++ クラスが作成されます。C++: 抽象メソッドを使用して抽象クラスを作成し、サブクラスでメソッドをオーバーライドする を参照してください。

仮想メソッドが行うことは、実装の詳細を派生クラスに任せながら、クラスの派生クラスを使用するオブジェクトが特定のインターフェイスに依存できるようにするメカニズムを提供することです。したがって、これは Java インターフェースに似ています。C++ 仮想メソッドは、ランタイム アプローチではなく、コンパイルされた静的チェック アプローチを使用して Java インターフェイスを実装する方法を提供する方法です。

仮想メソッドを使用して、派生型から変数を割り当てることができるポインター変数を作成するために使用できるスーパークラス型を作成します。仮想メソッドを使用すると、派生クラスから正しいメソッドが呼び出されます。どのメソッドを呼び出すかは、実行時ではなくコンパイル時に決定されます。C++ の主なアイデアは、C と同じくらい効率的でありながら、オブジェクト指向言語構造をコンパイル時に静的型チェックとともに提供して、実行時のエラー検出への依存を軽減し、追加のオーバーヘッドを削減することです。

class Joe {
public:
virtual int thingOne() { return 1;}  // standard, not pure virtual method
..
};

class JoeTwo : public Joe {
public:
int thingOne() { return 2;}   // derived class provides its own version of the method
..
};

Joe *myJoe = new JoeTwo;

int i = myJoe->thingOne();  // value of 2 put into i and not value of 1

C++ では、派生オブジェクトを含む変数が派生オブジェクトのスーパー クラスを含む変数に割り当てられるときに発生する可能性があるオブジェクト スライスのため、オブジェクトとオブジェクトへのポインターの違いを認識する必要があります。この「オブジェクトのスライス」は、派生オブジェクトが派生元の基本クラスまたはスーパークラス オブジェクトに適合しないために発生します。派生オブジェクトには、スーパー クラス オブジェクトにはない追加要素があるため、代入 (デフォルトの代入は単純なメモリ コピーです) では、派生オブジェクトのスーパー クラス部分のみがスーパー クラス オブジェクトにコピーされます。

class Joe {
public:
virtual int thingOne() { return 1;}  // standard, not pure virtual method
..
};

class JoeTwo : public Joe {
public:
int thingOne() { return 2;}   // derived class provides its own version of the method
..
};

Joe *myJoe = new JoeTwo;    // no object slicing since this is pointer
JoeTwo myJoeTwo;
Joe  myJoeSliced = myJoeTwo;  // JoeTwo object myJoeTwo sliced to fit into Joe object myJoeSliced
于 2013-01-06T19:36:21.597 に答える
6

Java と C++ の主な違いは、Java ではすべての関数がvirtual.

歴史的に、C++ が開発されたとき、すべての関数呼び出しの間に抽象化レイヤーを配置するという事実 (つまり、仮想メソッド テーブルを使用して行われること) は、仮想メソッドの呼び出しが遅いため、すべてのメソッド呼び出しに必要なものではありませんでした。

したがって、動的バインディングを介してメソッドを呼び出す必要があることを指定する必要があります。そうしないと、変数の宣言に従ってコンパイル時にメソッドが選択されます。これは、仮想ではないメソッドを宣言Base *b = new Derived()して呼び出すと、bコンパイル時にメソッドが選択され、Base::method.

モットーは、使わないものにはお金を払わない、それだけです。

C++ のインターフェイスは存在しませんが、基本的に同じように動作する純粋な仮想関数だけを持つクラスを作成できます。実際には、次の 2 種類の仮想メソッドを使用できます。

class Base {
  virtual void method() {
    //implementation
  }
  virtual void pureMethod() = 0;
}

最初method()は仮想で動的バインディングに従いますが、基本クラスでも実装されますがpureMethod()動的バインディングに従いますが、純粋仮想として宣言されているため実装Baseがなく、そのままインスタンス化することはできず、サブクラス化する必要があります少なくとも純粋仮想メソッドをオーバーライドします。

于 2013-01-06T19:17:48.827 に答える
4

C++ には Java のようなインターフェースはありません。最も近いのは、純粋仮想関数のみを持つクラスを定義して、そのクラスから派生したすべての人がそれらすべてを実装することを強制する場合です。

于 2013-01-06T19:14:14.090 に答える
2

C++ の仮想メソッドは、オーバーライドできるメソッドです。純粋仮想メソッド ( virtual foo() = 0のように定義) は抽象メソッドです。Java で使用するようなインターフェースを作成するには、すべてのメソッドが純粋仮想 (抽象) であることを指定するだけです。

ただし、「インターフェイス」は、通常は完全にヘッダー内にあるクラスのパブリック メンバーと型を参照している場合があります。

于 2013-01-06T19:16:00.263 に答える
2

C++ クラスのインターフェイスは、ヘッダー ファイルで定義されます。仮想関数は、サブクラス化して継承を使用する場合にのみ使用されます。

C++ で Java のようなインターフェイスに最も近いのは、純粋な抽象クラスを使用する場合です。このインターフェースを持つ実装クラスは、この抽象クラスをサブクラス化する必要があります。

デコンストラクターを仮想にすることを忘れないでください。そうしないと、基本クラスを参照するときにサブクラスのデコンストラクターが呼び出されません。

例:

class PuppetInterface
{
public:

    virtual ~PuppetInterface() {};

    virtual void walk() = 0;

    virtual void tellALie() = 0;
};

class Pinocchio : public PuppetInterface
{
public:

    ~Pinocchio()
    {
        //lie down look dead.
    }

    void walk()
    {
        //try moving wooden legs.
    }

    void tellALie()
    {
        //let nose grow look serious.
    }
};

int main(int argc, const char * argv[])
{
    PuppetInterface* pinocchio = new Pinocchio();
    pinocchio->walk();
    pinocchio->tellALie();

    delete pinocchio;

    return 0;
}

編集:生のポインタは悪いので、例外保存ではなく、リークする可能性があるなどです。上記のコードは次のように書き直す必要があります

//using c++ 11
int main(int argc, const char * argv[])  
{
    auto pinocchio = std::unique_ptr<PuppetInterface>(new Pinocchio());
    pinocchio->walk();
    pinocchio->tellALie();  
 }
于 2013-01-06T19:46:11.217 に答える