2012-06-26 7 views
6

私はその唯一の非静的メンバ関数を仮想することができることを理解して言ってから始めますが、これは私が欲しいものです:スタティック関数のオーバーロードはありますか?

  1. インタフェースを定義する基本クラス:私は機能にアクセスするために、基本クラスのポインタを使用することができます。
  2. メモリ管理のために(これは制限されたRAMを備えた組み込みシステムです)私は、オーバーライドする関数を静的に割り当てる必要があります。静的関数では、関数内のデータをどのように操作できるかという制約があるという結果を受け入れます。

    私の現在の考えは、実際には静的な関数のラッパーにすることで、軽いオーバーロード機能を維持できるということです。

私のデザインを再考する必要があることを伝えてください。これが私が質問している理由です。私がCを使用してコールバックを使用する方が良いと言いたいのであれば、オブジェクト指向のアプローチを使用することの落とし穴を説明するために、いくつかの読み物を私に指示してください。私が列挙した要件を満たすオブジェクト指向のデザインパターンがありますか?

+2

「静的」と言うとき、「非仮想」を意味しますか?あなたが "過負荷"と言うとき、あなたはむしろオーバーライドを意味するのですか?オーバーロードは同じ名前ですが、引数が異なるため、異なる関数です。上書きは同じ引数であり、オーバーライドされた関数を仮想にする必要があります。 – MvG

+0

@MvG私は区別がつかなかった。オーバーライドは私が後にしていることです。私はそれを編集します。 – 2NinerRomeo

+0

@ VanDarg:プログラムが組み込みシステム上で実行されているという事実は、スタックスペースを消費しないという欲求を引き起こしています。私は思う(しかし、私はこれまでに間違っていたし、これで新しくなった)。静的関数を宣言すると、コードをフラッシュに保存することが可能になるはずです。 – 2NinerRomeo

答えて

7

私が列挙した要件を満たすオブジェクト指向のパターンがありますか?

はい、プレーンな古い仮想関数です。あなたの望みは、「静的に割り当てられる優先機能」です。仮想関数は、静的に割り当てられたです。つまり、関数を実装するコードは一度だけ存在し、コンパイル/リンク時に固定されます。リンカコマンドに応じて、他の機能と同じようにフラッシュに格納される可能性があります。

class I { 
    public: 
    virtual void doit() = 0; 
    virtual void undoit() = 0; 
}; 

class A : public I { 
    public: 
    virtual void doit() { 
    // The code for this function is created statically and stored in the code segment 
    std::cout << "hello, "; 
    } 
    virtual void undoit() { 
    // ditto for this one 
    std::cout << "HELLO, "; 
    } 
}; 

class B : public I { 
    public: 
    int i; 
    virtual void doit() { 
    // ditto for this one 
    std::cout << "world\n"; 
    } 
    virtual void undoit() { 
    // yes, you got it. 
    std::cout << "WORLD\n"; 
    } 
}; 

int main() { 
    B b; // So, what is stored inside b? 
     // There are sizeof(int) bytes for "i", 
     // There are probably sizeof(void*) bytes for the vtable pointer. 
     // Note that the vtable pointer doesn't change size, regardless of how 
     // many virtual methods there are. 
     // sizeof(b) is probably 8 bytes or so. 
} 
2

静的メンバー関数は、クラスの名前空間内にある単なる関数(メンバー以外の関数など)です。それはあなたが、プレーンの機能のように扱うことができることを意味し、次の解決策が実行する必要があります。

class Interface 
{ 
    public: 
    void (*function)(); 
}; 

class Implementation: public Interface 
{ 
    public: 
    Implementation() 
    { 
     function = impl_function; 
    } 

    private: 
    static void impl_function() 
    { 
     // do something 
    } 
}; 

その後、

Implementation a; 
Interface* b = &a; 
b->function(); // will do something... 

このアプローチの問題点は、コンパイラがあなたのために行い、ほぼ何やっているだろうということです仮想メンバ関数を使用すると、コードの必要性が少なくなり、エラーが発生しにくくなり、実装関数へのポインタが共有されます。主な違いは、virtualを使用すると、呼び出されたときに(表示されない)thisパラメータが表示され、メンバー変数にアクセスできることです。

このように、私は単純にこれをしないで、通常の仮想メソッドを使用することをお勧めします。メモリ管理の目的のために

2

(これは 限られたラムと組み込みシステムである)私は、オーバーライド機能が静的 割り当てられるたいです。

C++のすべての関数は、常に静的に割り当てられます。唯一の例外は、JITを手動でダウンロードして利用する場合です。

0

仮想関数のオーバーヘッドは2倍です。実際の実装のコード(コードセグメントに存在し、他の関数と同じように)のほかに、仮想関数テーブルがあります。そのテーブル。仮想ファンクションテーブルは、派生した各クラスのために1度存在し、そのサイズは仮想ファンクションの数に依存する。。すべてのオブジェクトは、仮想関数テーブルへのポインタを持っていなければなりません。

私の指摘は、仮想関数のオブジェクトごとのオーバーヘッドは、あなたが持っている仮想関数の数にかかわらず同じか、それらに含まれるコードの量です。したがって、ある程度の多態性が必要であると判断したら、仮想関数を配置する方法はメモリ消費にほとんど影響しません。

関連する問題