26

これが私が入っているボックスです。「インターフェイスクラス内に仮想デストラクタを配置する」ことが重要である理由を理解したいと思います。最後までがんばれば、引用符で囲まれている理由がわかります... また、すべての語彙を完全に正しいものにしたいと考えています。これまでのプロセスで私がいる場所は次のとおりです。

  1. 基本クラスがある場合もあれば、基本クラスから継承する派生クラスがある場合もあります。

  2. 派生オブジェクトを指しているベースポインターがあり、さらに派生オブジェクトを指すそのベースポインターから行われたメンバー関数呼び出しを、実際に呼び出されたかのように動作させたい場合派生オブジェクトから、呼び出すメンバー関数は、基本クラスで仮想として宣言する方がよいでしょう。

  3. インターフェイスは、純粋仮想関数のみを持つ任意のクラスです。このインターフェイス クラスから新しいクラスを派生させ、すべての純粋仮想関数を実装すると、最終的に派生クラスのインスタンスを作成できます。

  4. インターフェイス クラスのインスタンスを持つことはできませんが、インターフェイス クラスへのポインターのインスタンスを持つことはできます。

  5. 派生クラスのオブジェクトを実際に指すインターフェイス クラスへのポインターがある場合 (実際には、#4 が正しい場合は常にそうする必要があると思います)、およびそのオブジェクトを削除することにした場合あなたのポインタ、そして「インターフェースクラス内に仮想デストラクタ」がない場合、派生オブジェクトを破壊する意図は、ベースオブジェクト(つまりインターフェースクラス)を破壊するための呼び出しとしてのみ実行されます。仮想デストラクタでは、派生オブジェクトのデストラクタが実際に呼び出されるポイントに到達することはなく、メモリ リークが発生します。

ふぅ。わかりました、それが正しければ、私の質問に移ります。次のように、インターフェイス内で仮想デストラクタを宣言するだけで十分ですか。

virtual ~iFace();

それは私には間違っているように見えます...だから、次のようにデストラクタを純粋仮想にするとどうなりますか:

virtual ~iFace() = 0;

それらは単なる宣言であるため、これらのいずれかが「インターフェイス クラス内の仮想デストラクタ」としてカウントされますか? 宣言されているが定義されていないデストラクタを使用できますか? それが純粋な仮想である場合にのみ、私は推測します...

とにかく、タイトルの質問に戻ります...私は本当にできる限り速く進んでいます...これがお金のショットです...「インターフェースクラス内の仮想デストラクタ」が少なくともこのような空の定義を必要とする場合:

virtual ~iFace() {};

次に、そのメンバー関数は純粋仮想ではありません (定義を指定したため、そうではありません)。したがって、クラスはインターフェイスではなくなります (純粋仮想メンバー関数だけが含まれているわけではありません)。

これは、インターフェイスの仮想デストラクタを定義すると、インターフェイスがなくなることを意味します (ただし、いくつかの抽象基本クラスのみ)。これはただの言葉遣いですか?何が起こっているのか理解できますか?

注: これはすべて、「インターフェースとは何か?」という自問自答から生まれました。次に、この質問の回答を読んでください: C++ でインターフェイスを宣言するにはどうすればよいですか?

短すぎるライドでは長すぎないことを願っていますが、これらの概念とそれに関連する語彙を完全に理解することを決意しています.

4

4 に答える 4

28

Abstract classデストラクタが仮想であり、定義が必要なのはなぜですか?

delete派生クラスオブジェクトと仮想デストラクタを持たないBaseクラスを指すポリモーフィックBaseクラスポインタを呼び出すと、未定義動作が発生します。

したがって、ポリモーフィックBaseクラスのデストラクタをとして宣言する必要がありますvirtual。デストラクタを明示的に仮想として宣言したら、その定義を提供する必要があります。これは、コンパイラがデフォルトですべてのクラスのデストラクタを生成(定義)するためですが、デストラクタを明示的に宣言すると、コンパイラはそれを行わず、独自のデストラクタの定義を提供します。コンパイラは、明示的な宣言をデストラクタで重要な操作を実行したいことを示すものと見なし(必要がない場合でも)、強制的に実行する機会を提供するため、これは理にかなっています。定義。


神話1:C++に
はと呼ばれるものがあります。Interface

言語としてのC++は、C++で呼ばれる ものを
提供しません。C++での動作をシミュレートするために使用されます。InterfaceInterfaceAbstract classAbstract ClassesInterface

抽象クラスとは何ですか?
定義上、抽象クラスには少なくとも1つの純粋仮想関数が必要です。


神話2:
抽象クラス内のすべての関数は純粋な仮想である必要があります。

いいえ
Abstract classes、その中のすべての関数が純粋な仮想である必要はありません。抽象オブジェクトは、少なくとも1つの純粋仮想関数を持っている場合は作成できません。しかし、あなたが正しく述べたように、あなたはそれへのポインタを作成することができます。


神話3:
純粋仮想関数は定義を持つことができません。

いいえ
純粋仮想関数に定義があることは完全に有効です。


なぜ私はPure virtual function定義付きが必要になるのでしょうか?
コードは言葉よりも大きく話すので、ここに簡単な例があります:
警告:デモンストレーションのためだけにコンパイルされていないコード

class IMyInterface
{
    int i;
    int j;
    public:
        virtual void SetMembers(int ii, int jj)=0;
};

/*The pure virtual function cannot be inline in the class definition*/
/*So this has to be here*/
void IMyInterface::SetMembers(int ii, int jj)
{
    i = ii;
    j = jj;
}

class Myclass: public IMyInterface
{
    int k;
    int l;
    public:
        virtual void SetMembers(int ll, int m, int a, int b)
        {
             k = ll;
             l = m;
             IMyInterface::SetMembers(a,b);
         }
};

int main()
{

    MyClass obj;
    obj.SetMembers(10,20,30,40);
    return 0;
}
于 2011-08-06T13:14:36.200 に答える
10

C++にはネイティブインターフェイスエンティティがありません。インターフェイスは通常のクラスとして実装されます。

したがって、クラスをC ++のインターフェイスにするのは、普遍的な合意があるものではありません。個人的には、データメンバーがなく、ユーザーが宣言したコンストラクターがなく、すべての関数が純粋な仮想である場合(デストラクタを除く可能性があります)、クラスはインターフェイスであると考えています。インターフェイス。クラスがこれらのプロパティのすべてに完全に適合しない場合、私はそれを「ファット」インターフェースと呼ぶかもしれません(一般的には褒め言葉ではありません!)。

基本クラス(「インターフェイス」クラスなど)へのポインタを介して動的に割り当てられたポリモーフィッククラスを削除する場合は、基本クラスのデストラクタを宣言する必要virtualがあります。これは、ユーザーが宣言したデストラクタである必要があり、暗黙的に宣言されたデストラクタではないことを意味しますvirtual

デストラクタを明示的に宣言したら、その実装を提供する必要があります。(基本クラスのデストラクタは、基本クラスのデストラクタが純粋な仮想、仮想、または非仮想として宣言されているかどうかに関係なく、派生したクラスのインスタンスを破棄するときに常に使用されます。)これは純粋にC++言語の実装の詳細です。基本クラスが「インターフェイス」であるという意味ではありません。インターフェイスクラスがある場合は、どのような場合でもデストラクタの実装が空になる可能性が非常に高くなります。メンバーや基本クラスがありません。気になるメンバー。

インターフェイスに少なくともいくつかの純粋仮想関数がある場合、デストラクタを純粋としてマークすることに実質的なメリットはありません。インターフェイスクラスはすでに抽象クラスです。派生クラスのデストラクタは、基本クラスのデストラクタを技術的にオーバーライドしないため、ユーザーが宣言したデストラクタなどを提供するために派生クラスを必要としません。

デストラクタを純粋な仮想として宣言すると、クラス定義でデストラクタの定義をインラインで提供する機能も失われますが、これは小さな詳細です。

于 2011-08-06T13:27:43.157 に答える
7
于 2011-08-06T13:18:18.787 に答える
2
  1. わかった。
  2. わかった; メンバー関数が基本クラスで仮想として宣言されていない場合、基本クラスの関数が呼び出されます。メンバー関数が基本クラスで純粋仮想として定義も宣言もされていない場合、エラーが発生します。
  3. C ++では、JavaやC#のようなインターフェイスはありません。C ++の抽象基本クラスは、後者の2つの言語に存在するため、インターフェースと抽象クラスを組み合わせたものです。C ++クラスは、少なくとも1つの純粋仮想メンバー関数を持っている場合は抽象です。
  4. インターフェイス抽象クラスに置き換えます。
  5. 正式には、基本クラスのデストラクタが仮想として宣言されていない場合に、基本クラスへのポインタから派生クラスを削除するとどうなるかを推測することはできません。

これらすべてを考慮すると、一般に、抽象基本クラスには、インスタンス化できないことを保証する純粋仮想メンバー関数がすでに含まれているため、通常の方法は、何もしないインライン仮想デストラクタを定義することです。

于 2011-08-06T13:31:18.967 に答える