2011-01-17 9 views
6
#define dItemName  L"CellPhone" 
+0

http://stackoverflow.com/questions/3474949/over-reliance-on-macros/3475032#3475032 – DumbCoder

+0

Scott Meyersの「Effective C++」をチェックしたいと思うかもしれません。私は第3版が最新版だと思います。彼はこれと他の多くの同様のC++の問題に対処する素晴らしい仕事をしています。 – westsider

+0

この 'dItemName'の使用方法は?例を追加してください。 – i486

答えて

13

定数変数として定義します。それは良いプログラミング実践です。

const wchar_t dItemName[] = L"CellPhone"; 

また、の#defineが悪い理由:それはあなたが使用するすべての場所を変えるあなたは、配列として定義、どこかに後で文字列のな長さを知っておく必要がある場合には

const wchar_t *dItemName = L"CellPhone"; 

単語dItemNameをL "CellPhone"に変換します。例:

struct { 
    int dItemName; 
} SomeStruct; 

は無効となります:#define

struct { 
    int L"CellPhone"; 
} SomeStruct; 
+0

まあ、リテラルはすでに強く型付けされていますが、alaです。あなたはa *がありません。 –

+0

'*'や 'std :: wstring'を忘れましたか? –

+0

あなたは正しいです、*が追加されました。 –

6

一つの大きな問題は、言語自体の外にあり、したがって、与えられた範囲に限定されないことです。あなたは、私がconst std::wstring dItemName = L"CellPhone";

1

#defineマクロを定義するプリプロセッサ命令であると交換したいなど

すべての名前空間、クラス、関数内の翻訳単位でdItemNameどこでも、置き換えられます。あなたのケースではdItemNameマクロの値はL"CellPhone"です。

マクロは、実際のコードが処理される前に処理されているために悪いです。これは、スコープとC++構文の規則に従わないことを意味します。 dItemNameという名前の変数がある場合は、おそらく動作しません。そのため、コンパイルエラーが分かりにくいでしょう。

解決策は、dItemNameを変数(この場合はconst変数)として宣言することです。

1

あなたが作成したプリプロセッサマクロはすべての名前スコープを汚染するので、それらはどこにでもあり、標準的な命名範囲ルールに従わない。したがって、そのようなマクロでは、の代わりにint dItemName = 5;のようなコードがプリプロセッサによってf'edされます。定数のグローバル変数はこれをしません。

他のすべての問題はさておき、これはIMNSHOのマクロ定義の問題です。

6

私はすべての欠点を指摘している1つの質問を見つけることができませんでした。

まず、C(これはC++ではありません)ではなく、定数を宣言する方法です。なぜなら、多くのC++開発者がCのバックグラウンドを持ち、Cのバックグラウンドを持つ人々から教えられた/教わったことがあったとき、彼らはこのC-ishの振る舞いを再現する傾向があります。

しかし、C++では優れた機能を備えています。

#defineは定数を定義していない、それはマクロがない範囲

  • マクロを知らないマクロ

    1. を規定する安全

    を入力されていないマクロには範囲を知りません

    これらはプリプロセス機能です。プリプロセッサは、基底言語(asm、CまたはC++のいずれか)の規則を認識せず、常にシンボルを展開しますそれはスコープを考慮しないで在庫があります。このため

    は、通常のマクロを離れて設定するシンボルの特定のセットを使用することをお勧めします。人々は一般的に、あなたがそれを覚えておく必要があるものの、ALL_CAPS記号を使用しています。

    • 彼らはアンダースコアCに準拠するために

    ことから始めるべきではありません

  • 彼らは二つの連続アンダースコアを含めることはできません++標準。

    マクロは、タイプセーフではありません。

    私が言ったように、プリプロセッサは、基礎となる言語規則を無視し、したがって、以下の奇妙なとしてそれに当たらない:

    :一方

    #define FOO "foo" 
    
    int main(int argc, char* argv[]) 
    { 
        if (FOO) { ... } 
    
        return 0; 
    } 
    

    を、適切な型を使用すると、この意図しないミスを防止するであろう

    std::string const Foo = "foo"; 
    

    結論?

    あなたが望むなら、それはちょうどあなたの代わりに、コンパイラの余分な作業をやっている#defineを使用することができますが、それはあなたの呼び出しです。個人的に:私は怠け者だ:)

  • +0

    私はobj-cの開発者ですが、最近は定数を定数変数に変換し始めています(Al Keppの答え​​を参照)。これは最初に定義されたマクロです。コード実行と定数定義でない場合は、#define?(特に、obj-cでは特にない)を使用するのがよいでしょうか? –

    +0

    @YunusNedimMehel:主な使用例はロギングマクロです。ロギングが呼び出されるポイントで '__FILE__' /' __LINE__'へのアクセスを望むなら、関数はインラインでさえ、ポイントからではなく、定義されているところで '__FILE__/__LINE__'を使用するので、マクロが必要です-of-use。同様に、関数内のクリーンアップセクションの名前に対してプロジェクト全体の規約を持つC(C++で/RAⅡ&例外では重要ではない)の場合、チェックを返すマクロとクリーンアップセクションは 'goto'ではありません恐ろしい(代わりのものは矢印パターンです)、マクロだけが使用時点のスコープで「動く」ことができます。 – ShadowRanger

    1

    は、障害があると彼らはのために発明ところ何を定義するためにポインティング - だけでなく、切削用ナイフを非難します。

    UPPERCASE_NAMESを使用して定義を正しく指定しないと、問題が発生しますが、作業スタイルを自習することができない場合は、C言語で問題が発生します。

    constを使用して動的再配列システムを生成することはできません。そのため、組み込みアプリケーションには適していません。使用法にあらかじめコンパイルしておく必要があります。事前評価定数だけを割り当てることができます。ツールdoeseがOO-パラダイムのは突然無駄にならないに屈するないという理由だけで

    。 Constは、機能に関しては等価置換ではありません。

    関連する問題