ます。http://hi.baidu.com/todaygoodhujun/blog/item/7b3b7cecf4c716d12f2e2132.htmlからの振替
C言語の多型を達成するために
、私はあなたがどんな経験を持っているか、多くの人がデザインパターンの本を見ていると信じて?ブリッジ、プロキシ、工場のデザインパターンは、抽象クラスに基づいています。抽象オブジェクトは、ここにコアです。
実際に、私は心の問題のプログラミングフレームワークは、一般的に、オブジェクト指向プログラミングの考えられている抽象オブジェクトの抽象的、ボディビルディングフレームワークプログラムだと思います。スケルトン抽象の構築、完全なプログラムを形成するために結合された多型。C ++言語自体は継承やポリモーフィズムを実装しているため、このようなプログラミングの概念(アイデアはあなたが笑、風で?意味しています)C ++で非常に一般的な現象で、仮想(多型)に言うことができるの使用は、VCの魂です。
しかし、C言語を使用して、我々はほとんどこの多型は滑らかであることを忘れて置きます。私は、多くの場合、古い世代のクラスを聞いたことありますか?ポリモーフィック?私たちは、これらは忘れて、Cを使用しています。残念ながら、私は頑固な人です。このような良いこと、なぜをしません。非常に満足して、いくつかの最近の純粋なCのコードでは、私はC多型を見ました!以下はゆっくり来る私に耳を傾けます。
1. VCは、どのようなインタフェースである
インタフェース:中国の説明は、インターフェイスが、実際には、それは純粋仮想クラスを表しています。しかし、私は、インターフェイスの定義を見つけ、VCインタフェースで実際に構造体である、ことを言わなければならない、あなたはこのマクロ定義を見つけることができます:
#ifndefのインタフェース
の#defineインタフェース、構造体
の#endif
そして、実際には、VC、クラスの場合をそこに仮想関数、vtableのは、それが実際に仮想関数のリストであるだろうクラス。実際にはC ++はCから進化したが、それはC言語では多くの新機能のための言語レベルのサポートで、我々はまた、この機能を使用することができ、前提は、我々は自分自身を達成しなければならないということです。
2。達成するためにどのようにC純粋仮想クラス(私は純粋仮想構造、それを呼び出す)
が比較的早く、私たちは突然光を見ると信じています。関数ポインタの組み合わせを使用した構造体は、純粋仮想クラスを実現することができます。
例:構造体{typedefは
ボイド(* FOO1)();
CHAR(* foo2は)();
チャー*(* Foo3)(CHAR * ST);
} MyVirtualInterface;
私たちは、ブリッジモードで車体フレームを使用したいと仮定する。今、私はこれらのご紹介になります(私たちの主なクラスは、インタフェースの実装クラスは、ACT1、ACT2で、DoMyActである)「のクラスを。」(ここでの説明の前に「クラス」にC、変更、以前の配列のアプローチを使用して)
メインクラスDoMyAct:メインクラスはMyVirtualInterface * m_pInterfaceを含み、マスタークラスは、機能を有している:
DoMyAct_SetInterface(MyVirtualInterface * pInterface)
{
= pInterface m_pInterface;
}
DoMyAct_Do()
{
(m_pInterface == NULL)戻った場合は、
m_pInterface-> FOO1();
C = m_pInterface-> foo2はは();
}
ACT1のサブクラス:MyVirtualInterface ST [MAX]を含む、仮想構造を実装し、以下の機能を有する:
MyVirtualInterface Act1_CreatInterface(* )
{
インデックス= FindValid()//ターゲットプールまたは使用mallocの!、アプリケーションのうちの一例とどまるべき
IF(インデックス== - 1)戻りNULL;
セント[インデックス] = .Foo1 Act1_Foo1; Act1_Foo1は、以下の//で具現化することが
セント[インデックス] = .Foo2 Act1_Foo2。
ST [インデックス] = .Foo3 Act1_Foo3;
リターン&ST [インデックス];
}
サブクラスACT2前掲。
メインでは、オブジェクトのリストがあると想定されます。リストMyVirtualInterfaceがポインタに格納され、そこにある:
(!(P = Act1_CreatInterface())= NULL)IF
List_AddObject(&リスト、P); //すべての追加
しばらく(P = List_GetObject()){
DoMyAct_SetInterface(P); //代わりに、元の偉大な長さのケーススイッチのインターフェイスを使用し
DoMyAct_Do(); //それを行う具体的な行動の種類、気にしない
}
FREE ALLを。
このような一般的に使用される埋め込み、オブジェクトプーリング技術として内部マイクロシステムでは、この時間は、放出空間の一時的なプール割り当ての関数とオブジェクトの配列を適用する添付使用し、以前にプール空間オブジェクトではない(問題を考えることはできませんこの関数は)リリースで、オブジェクトプーリングを終了します
しかし、PC環境では、原因のプログラムの比較的大きなサイズに、より重要なのは、オブジェクトの人生を作るいくつかの特別な要件は、アプリケーションの体外で機能し続ける必要があり、あなたもC ++、新しいで、実際には、malloc関数を使用する必要がありますオブジェクトを自動的に解放することは、常に頭痛の問題であり、新しい標準はスマートポインタを紹介します。しかし、私は個人的に、私が信頼することができない問題は、マシンを完了するために、メモリを解放すると思い、それが唯一の次善達成することができます。
あなたは、それはそれJavaのガベージコレクションアルゴリズムの設計がいかに困難を知っていますか?現実の世界では非常に困難で正確な結果を得るためには、事前条件なしに、複雑です。だから私は、プログラマが常に堅牢、無料となります心に留めておくべきで、自己防衛の手順は別の記事で説明します、と述べました。
3。純粋仮想構造の分解は
唯一の機能である構造体がある場合、私たちは何を見てみましょうか?我々は唯一の関数ポインタを使用して、構造体を使用しない場合は、この時間は、その後、何がありますか?私たちは、これが関数ポインタの通常の使用に縮退することがわかりました。
だから、時々私は、オブジェクト指向は単なる形式ではなく、技術だと思います。視点ではなく、アルゴリズムよりも、です。しかし、分子式がCであるが、この方法は、同じ組成でなくても、カーボン、グラファイト、ダイヤモンドとの間の関係として、パフォーマンスは完全に異なっています!
時には、私たちは多くの場合、プログラミングで些細な物事に悩まさが、重力の中心からずれている、実際には、プログラムの特性を進化させることができ、非常に重要です。これは、初めて成功しなかった、可能ですが、限り進化として、開発することができます。
4。アドバンスト-クラスツリー、親クラスではない、純粋仮想クラス
単にケースを話す以上は、親クラスは純粋仮想設定(対象は全てのベースクラスのために推奨される最初から純粋仮想クラスである)であり、複数のクラス階層は、親クラスの出現がないときにどのように純粋に架空の構造を行います。ねえ、実際には、Cで実装することはC ++より簡単でよりです。C以来、各関数に分散されています。
本明細書で使用する場合、マクロ定義は良い方法である:例えば、二つのクラスACT1、ActByOther1 "継承" ACT1:
MyVirtualInterface ActByOther1_CreatInterface *()
{
インデックス= FindValid()//オブジェクトプーリングまたはmallocの使用
IF(インデックス== - 1) NULL戻り、
セント[インデックス] = .Foo1 ActByOther1_Foo1; // Act1_Foo1以下で実施すること
セント[インデックス] = .Foo2 ActByOther1_Foo2;
セント[インデックス] = .Foo3 ActByOther1_Foo3;
リターン&ST [インデックス];
}
の#define ActByOther1_Foo1 Act1_Foo1 / /これはちょっと継承され
ActByOther1_Foo2(){} //その実現を変更することができ
ActByOther1_DoByOther(){} //新しいコースがわずかに達成することができます
5。例- NalToolは、純粋仮想構造であることを特徴とする請求H264源に見出すことができます。
ます。https://my.oschina.net/dake/blog/196720で再現