C++可変パラメータ関数の実現方法


C++可変パラメータ関数の実現方法
C++プログラミングで可変パラメータ関数を実現するには多くの方法があり、本稿では最も一般的な実現方法を紹介し、パラメータマクロを変更する方法を紹介する:パラメータ生命は省略符であり、関数実現時にパラメータリストマクロでパラメータにアクセスする.
1.可変パラメータマクロ実現パラメトリック関数
可変パラメータマクロインプリメンテーションは、次のステップに分けられます.
  • 関数パラメータプロトタイプには省略符が与えられる.
  • 関数インプリメンテーションでva_を宣言list可変パラメータリスト変数;
  • 初期化構築va_の開始list変数;
  • は変更リストにアクセスします.
  • 清掃作業を完了する.

  • 上記の手順の実装には、4つのマクロを使用する必要があります.
  • va_list
  • void va_start(va_list ap, last_arg)
  • type va_arg (va_list ap, type)
  • void va_end(va_list ap)
  • va_list   C             
    void va_start(va_list ap, last_arg)
    ap :    va_list      ,        va_arg              。
    last_arg :                  ,         。
       :type va_arg (va_list ap, type)
                  ,type       ,     ,ap              ,  ap      ,      type    。 ap arg_ptr      。
    void va_end(va_list ap)
          va_start              。               va_end,       。

    これらのマクロはヘッダファイルstdargにあります.hで定義を宣言する.そのため、このヘッダファイルを含める必要があります.
    使用例を次に示します.
    #include 
    
    //      sum(),         。
    
    //Step1:             
    int Sum(int count, ...);
    
    int Sum(int count, ...) {
        //Step2:           va_list        ;
        va_list ap;
        //Step3:        va_list  ,                
        va_start(ap, count);
        int sum = 0;
        for(int i = 0; i < count; i++) {
            //      ,             
            sum += va_arg(ap, int);
        }
        //    
        va_end(ap);
        return sum;
    }

    実際に可変パラメータマクロを使用してC++可変パラメータ関数のプログラミングを実現するには、いくつかの点に注意してください.
  • 関数プロトタイプの省略記号は、パラメータリストの末尾にある必要があります.すなわち、関数プロトタイプのパラメータリストの省略記号の右側に決定パラメータが表示されません.
  • 試用完了用va_endクリーンアップ作業の手順は不可欠です.そうしないと、メモリやリソースの漏洩を引き起こす可能性があります.
  • va_Listは1回のアクセスで後退することはできませんが、va_を複数回構築できます.listマルチアクセス;

  • 2.より安全な可変パラメータ関数の実現方法
    上記の例のコードでcountが渡された実パラメータについては、後述する場合...省略符に対応する実際のパラメータ数が一致しない場合、関数のリスクが発生する可能性があります.これらは運転時の具体的な状況に完全に依存しており、安全ではありません.
    もう1つのより安全な可変パラメータマクロ実装方法は、C++のattribute()特性を用いて可変パラメータの検査を支援することである.
    最も一般的な形式は次の2つです.
    __attribute__((format(printf, m, n)))  
    __attribute__((format(scanf, m, n)))

    ここで、パラメータmとnの意味は、m:いくつかのパラメータはフォーマット文字列(format string)である.n:パラメータセットの最初のパラメータ、すなわちパラメータ「...」の最初のパラメータは、関数パラメータの総数で何番目に並んでいますか.
    attribute formatプロパティは、宣言された関数にprintfまたはscanfのような特徴を加えることができます.コンパイラは、関数宣言と関数の実際の呼び出しパラメータとの間のフォーマット文字列が一致しているかどうかを確認できます.format属性はコンパイラにprintf,scanfなどの標準C関数パラメータフォーマット規則に従ってその関数のパラメータを検査するように教える.これは、デバッグ情報のインタフェースを自分でカプセル化するときに非常に役立ちます.
    formatの構文フォーマットは次のとおりです.
    format (archetype, string-index, first-to-check)
        ,“archetype”       ;“string-index”                   ;“first-to-check”                      。

    次に、2つの例を示します.
    一般的な関数:
    printf:extern void myprint(const char*format,...)に似た可変パラメータを持つ関数を定義します.attribute ((format(printf,1,2)));//m=1;n=2extern void myprint(int l,const char *format,...) attribute ((format(printf,2,3)));//m=2;n=3
    クラスメンバー関数
    特に、myprintが関数のメンバー関数である場合、mとnの値は、extern void myprint(int l、const char*format、...)など、少し「懸かっている」ことに注意してください.attribute ((format(printf,3,4)));
    これは、クラスメンバー関数の最初のパラメータが実際に隠れているthisポインタであるためです.