web-dev-qa-db-ja.com

C ++関数でのローカルクラスの使用

C++関数での内部構造体の使用法をいくつか見ます。

共通インターフェースIBaseがあります。これがドラフトコードです。

class IBase
{
    virtual Method()=0;
}

vector<IBase*> baseList;

次に、そのIBaseに基づいて関数が内部クラスを定義し、内部クラスオブジェクトをbaseListにプッシュしました。

void func()
{
    struct Object : public IBase
    {
        virtual Method()
        {
            // Method of Object in func
        }
    }

    IBase* base = new Object();
    baseList->Push(base);

}

奇妙な使い方のようですが、メッセージ/イベント作成パターンの素晴らしい実装です。

他のスレッドは、このbaseListを使用して着信イベントを処理する場合があります。

「構造体オブジェクト」の内部構造体のスコープは何ですか?とても面白いです。これについて話している文書はありますか?

37
giggle

「構造体オブジェクト」の内部構造体のスコープは何ですか?

ローカルクラスのスコープは、それらが定義されている関数ですが、それ自体は興味深いものではありません。

ローカルクラスを興味深いものにするのはifそれらが(コードのように)いくつかのインターフェイスを実装しているので、そのインスタンスを作成し(newを使用)、それらを返すことができます(たとえば、 std::vector<IBase*>)、これにより実装にアクセスできるようになります基本クラスポインターを介して関数の外部でもアクセスできます。

ローカルクラスに関するその他の事実:

  • 静的メンバー変数を定義することはできません。

  • 囲んでいる関数の非静的な「自動」ローカル変数にはアクセスできません。ただし、static変数にはアクセスできます。

  • テンプレート関数で使用できます。

  • テンプレート関数内で定義されている場合は、囲み関数のテンプレートパラメータを使用できます。

  • ローカルクラスは最終的なものです。つまり、関数の外部のユーザーは、ローカルクラスから関数に派生できません。ローカルクラスがない場合は、名前のない名前空間を別の翻訳単位に追加する必要があります。

  • ローカルクラスは トランポリン関数 を作成するために使用されます。通常はthunksとして知られています。


編集

規格からの参考文献(2003)

9.8ローカルクラス宣言[class.local]

\ 1。クラスは関数定義内で定義できます。このようなクラスはローカルクラスと呼ばれます。ローカルクラスの名前は、それを包含するスコープに対してローカルです。ローカルクラスは、外側のスコープのスコープ内にあり、外側の関数と同じように、関数の外部の名前にアクセスできます。ローカルクラスの宣言では、型名、静的変数、extern変数と関数、および包含スコープの列挙子のみを使用できます。

[Example:

int x;
void f()
{
   static int s ;
   int x;
   extern int g();

   struct local {
      int g() { return x; } // error: x is auto
      int h() { return s; } // OK
      int k() { return ::x; } // OK
      int l() { return g(); } // OK
   };
// ...
}
local* p = 0; // error: local not in scope

—end example]

\ 2。囲み関数は、ローカルクラスのメンバーに特別なアクセス権を持ちません。通常のアクセス規則に従います(11節)。ローカルクラスのメンバー関数は、定義されている場合、クラス定義内で定義されます。

\ 3。クラスXがローカルクラスの場合、ネストされたクラスYはクラスXで宣言され、後でクラスXの定義で定義されるか、クラスXの定義と同じスコープで後で定義されます。ローカルクラス内にネストされたクラスは、ローカルクラス。

\ 4。ローカルクラスは静的データメンバーを持っていません。

46
Nawaz

\ 4。ローカルクラスは静的データメンバーを持っていません。

しかし、あなたはローカルクラスの中でこれを行うことができます

int GetCount()
{
    class _local
    {
    public:
        static int Count(int count = std::numeric_limits<int>::max())
        {
            static int count_ = 0;
            if (count != std::numeric_limits<int>::max()) count_ = count;
            return count_;
        }

        static float Operation(float  a, float  b)
        {
            _local::Count(_local::Count() + 1);
            return a;
        }
    };
   _local::Count(0);
   CALLBACK( _local::Operation);
   return _local::Count();
}

_local :: Countを使用して、静的な変数を読み書きできます

-aydin

5
aydin

これは通常のC++です。 scope of struct Objectは関数funcのみです。ただし、このタイプのオブジェクトは、IBaseから継承するため、具体的なタイプがわからなくても使用できます。これは、実装をカプセル化するために使用されます。

2
Lindydancer

ローカルクラスの非常に興味深い使用法は、C++ 17でのCommodore 64ゲームのプログラミングに焦点を当てたCppConの講演でJason Turnerによって提示されています。彼は、機能レベルでRAII原則を使用する方法を示します。

彼は基本的に、このクラスのインスタンスを返す関数のローカルクラスのコンストラクターに不変式を確立します。したがって、不変の期間は、返されたオブジェクトの有効期間によって制御されます。これは、std::lockのようなRAIIラッパーが行うことと非常によく似ていますが、わずかに異なります。

あなたは ここの適切な部分を参照 できますが、私は彼のパフォーマンスをし、それをずっと見ることをお勧めします。

0
neonxc