[解決済み] C++からCへの移行
質問
C++で数年間コーディングした後、最近、組み込み分野でCでコーディングする仕事を依頼されました。
組み込み分野で C++ を否定することが正しいか間違っているかという問題はさておき、C++ には私がとても恋しくなるような機能/慣用句がいくつか存在します。ほんの少しですが、例を挙げてみましょう。
- 一般的な、型安全なデータ構造 (テンプレートを使用)。
- RAII。特に複数のリターンポイントを持つ関数において、例えば各リターンポイントでmutexを解放することを覚える必要がない。
- 一般にデストラクタ。例えば、MyClass のために一度 d'tor を書くと、MyClass インスタンスが MyOtherClass のメンバーである場合、MyOtherClass は明示的に MyClass インスタンスを初期化する必要がありません - その d'tor は自動的に呼び出されます。
- 名前空間。
C++からCに移行した経験を教えてください。
お気に入りの C++ の機能/慣用句のために、どのような C の代用品が見つかりましたか?また、C++ にあればいいと思う C の機能を発見しましたか?
どのように解決しましたか?
組み込みプロジェクトに取り組んでいて、一度オール C で作業してみたのですが、どうしても耐えられなかったのです。 あまりにも冗長で、何も読むことができなかったのです。 また、私が書いた組み込み用に最適化されたコンテナーは、安全性が低く、修正が困難な
#define
ブロックに変更しなければなりませんでした。
C++ではこうなっていたコード。
if(uart[0]->Send(pktQueue.Top(), sizeof(Packet)))
pktQueue.Dequeue(1);
に変わる。
if(UART_uchar_SendBlock(uart[0], Queue_Packet_Top(pktQueue), sizeof(Packet)))
Queue_Packet_Dequeue(pktQueue, 1);
は、おそらく多くの人が問題ないと言うでしょうが、1行で2つ以上の "メソッド" を呼び出す必要がある場合は、ばかばかしいことになります。 C++の2行がCの5行になってしまいます(80文字の行長制限のため)。 どちらも同じコードを生成するので、ターゲット プロセッサが気にするようなことではありません!
あるとき (1995 年頃)、私はマルチプロセッサのデータ処理プログラム用に多くの C 言語を書こうとしました。 各プロセッサが独自のメモリとプログラムを持っているようなものです。 ベンダーが提供するコンパイラーは C コンパイラー (ある種の HighC 派生) で、ライブラリーはクローズド ソースだったので、GCC を使用してビルドすることができませんでした。
あきらめる前に 1 か月ほどやってみたのですが、その間に cfront を見つけ、C++ を使えるように makefile をハックしました。 Cfront はテンプレートさえサポートしていませんでしたが、C++ のコードはずっとずっと明快でした。
一般的で型安全なデータ構造 (テンプレートを使用)。
C言語でテンプレートに最も近いものは、多くのコードでヘッダーファイルを宣言することで、次のようになります。
TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{ /* ... */ }
のようなもので引っ張ります。
#define TYPE Packet
#include "Queue.h"
#undef TYPE
これは複合型では動作しないことに注意してください。
unsigned char
を作らない限り)。
typedef
を最初に作らない限り
ああ、このコードが実際にどこにも使われていなければ、構文的に正しいかどうかさえもわからないということを忘れないでください。
EDITです。 もう一つ、あなたは 手動 でコードのインスタンス化を管理する必要があります。 もしあなたの "テンプレート" コードが すべて インライン関数でない場合、リンカーが "multiple instances of Foo" エラーの山を吐き出さないように、一度だけインスタンス化されることを確認するために何らかの制御を行う必要があります。
これを行うには、ヘッダーファイルの "実装" セクションに非インライン化したものを配置する必要があります。
#ifdef implementation_##TYPE
/* Non-inlines, "static members", global definitions, etc. go here. */
#endif
そして、その中の 一 をすべてのコードに配置します。 テンプレートバリアントごとに にする必要があります。
#define TYPE Packet
#define implementation_Packet
#include "Queue.h"
#undef TYPE
また、この実装部分には
の外側
標準の
#ifndef
/
#define
/
#endif
の連番で、テンプレートのヘッダーファイルを別のヘッダーファイルにインクルードしても、その後にインスタンス化する必要があるためです。
.c
ファイルでインスタンス化する必要があるからです。
そう、すぐに醜くなる。 だから、ほとんどのCプログラマーは試そうともしないのです。
RAII。
特に複数のリターンポイントを持つ関数において、例えば各リターンポイントでミューテックスを解放することを覚える必要がない。
さて、きれいなコードを忘れて、すべてのリターンポイント(関数の終わりを除く)に慣れるために
なり
goto
s:
TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{
TYPE * result;
Mutex_Lock(this->lock);
if(this->head == this->tail)
{
result = 0;
goto Queue_##TYPE##_Top_exit:;
}
/* Figure out `result` for real, then fall through to... */
Queue_##TYPE##_Top_exit:
Mutex_Lock(this->lock);
return result;
}
デストラクタ全般
例えば、MyClass のために一度 d'tor を書いておけば、MyClass のインスタンスが MyOtherClass のメンバであっても、MyOtherClass は明示的に MyClass インスタンスを初期化する必要がなく、自動的にその d'tor が呼ばれることになります。
オブジェクトの構築は、同じように明示的に処理されなければなりません。
名前空間です。
これは実は簡単に修正できるもので、単にプレフィックスを にプレフィックスを付けるだけです。 シンボルにプレフィックスを付けるだけです。 これは、先ほどお話したソースの肥大化の主な原因です(クラスは暗黙の名前空間なので)。 C の人たちはこれをずっと続けてきたので、おそらく何が大きな問題なのかわからないでしょう。
YMMV
関連
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み] C++で、あるコンストラクタを別のコンストラクタから呼び出す(コンストラクタ・チェイニングを行う)ことは可能ですか?
-
[解決済み] Visual Studio C/C++ コンソールアプリケーションでコンソールウィンドウが閉じないようにする。
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] 派生クラス関数から親クラス関数を呼び出すには?
-
[解決済み] std::vector<> からインデックスで要素を消すにはどうしたらいいですか?
-
[解決済み] gccでC/C++のソースからアセンブラ出力を得るにはどうしたらいいですか?
-
[解決済み] 関数からunique_ptrを返す
-
[解決済み] [Solved] プログラムが実行されているディレクトリを取得するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み] クラスにデフォルトコンストラクタが存在しない。
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる
-
[解決済み] C言語におけるエラー管理のためのgotoの有効な使用法?