C++クラスの可変引数化を禁止する方法

このQ&Aのポイント
  • C++クラスの可変引数化を禁止する方法を調査しています。
  • クラスのインスタンスをprintfの引数にすることをコンパイルエラーにする方法を知りたいです。
  • コピーコンストラクタや代入のオーバーロードをprivateにしてもエラーが出ないので、他の方法を探しています。
回答を見る
  • ベストアンサー

C++のクラスの可変引数化を禁止する方法。

C++のクラスの可変引数化を禁止する方法。 クラスのインスタンスをprintfの引数にするのをコンパイル・エラーにする方法はないでしょうか? コピーコンストラクタや代入のオーバーロードをprivateにしてもエラーが出ないので方法を探しています。 #include "stdafx.h" class CTest { private: int intdata; public: CTest() : intdata(0) { }; private: void operator =(const CTest& src) {} CTest(const CTest& src) {} }; int _tmain(int argc, _TCHAR* argv[]) { CTest ctest; printf( "%s %p\n", ctest, ctest ); return 0; }

  • zwi
  • お礼率80% (4/5)

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

こんな風にすれば、ある程度までエラーを検出できそうです。 #include <cstdio> inline int printf_arg(int arg) { return arg; } inline long printf_arg(long arg) { return arg; } inline double printf_arg(double arg) { return arg; } inline long double printf_arg(long double arg) { return arg; } inline const volatile void* printf_arg(const volatile void* arg) { return arg; } template <typename T> inline int printf(const char* format, const T& arg0) { return std::printf(format, printf_arg(arg0)); } template <typename T1, typename T2> inline int printf(const char* format, const T1& arg0, const T2& arg1) { return std::printf(format, printf_arg(arg0), printf_arg(arg1)); } // 以後、引数の数が異なるバージョンを必要なだけ定義 ただ、ローカルクラスだとすり抜けてしまうとか、問題も残っています。 確実にエラーを検出するには、何らかの名前空間内で定義して、明示的にその名前空間を指定するか、printfという名前をマクロですり替えるしかないのかもしれません。

zwi
質問者

お礼

コードをありがとうございます。 この方向でエラーを実装できるか試してみます。

zwi
質問者

補足

遅くなりました。 エラーが検知できそうです。ありがとうございました。

その他の回答 (2)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

現在の C++ の規格に従う限り「undefined behavior だからどうしようもない」としかいいようがない....

zwi
質問者

お礼

そうですよね。 ありがとうございます。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

printfはC言語由来のものだから、明示的にキャストしない限り、C++的な変換は行なってないと思うのですが。 また、GCCだとフォーマット文字列と引数の型に不一致があるとコンパイル時の警告はでますが、VCだとそれもんかったような。

zwi
質問者

補足

ありがとうございます。 実際のところ、MFCのCString::Formatでも同様の問題が出ているので困っています。 サンプルということでprintfで書かせていただきました。 何らかの演算子のオーバーロードをprivateにする事でガード出来ないものでしょうか? 私自身もすごく無理かも知れないなとは思っているですが。

関連するQ&A

  • _TCHAR*での引数の読み込み

    VC++2010での、通常の #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { return 0; } のウィザードを使って、arvg[1]やargv[2]に引数を与えて、本体内で通常のCで使う printf("%s\n", argv[1]); や fopen(argv[1], "r"); を使いたいのですが、引数の型が_TCHAR*になっているため文字がそのまま使えません。 int main(int argc, char *argv[]) で使えば問題なく使えるのですが、デフォルトのウィザードを使った時の使い方を知っておきたいのです。 御経験のある方、御教示お願い致します。

  • C++の質問です!

    課題なんですけど分からないです(泣) 解答お願いします(;;) 下記のプログラム中の(1)~(7)には何が入るか? #include <stdafx.h> (3) sho((4)) //関数sho の定義 { return((5)m/n); } void irekae(int (6),int (7)) //関数irekae の定義(2つの引数をp,q とする、型に注意!) { int k; k=(6); (6)=(7); (7)=k; } int _tmain(int argc, _TCHAR* argv[]) //関数_tmain の定義 { int i,j; double x; printf("整数i,j?:"); scanf("%d%d",&i,&j); (1); //整数i,j を引数として実数除算した商を返す関数sho を呼び出す。 printf("i/j=%f¥n",x); //結果の確認 (2); //整数i,j の値を入れ換える関数irekae を呼び出す。 (1); printf("i/j=%f¥n",x); }

  • c++ TCHARで文字化け

    TCHARはUNICODEが扱えるときいたので早速つかってみた。以下は引数を表示するプログラムである。 Visual C++ Express Editionを使った。 #include <stdio.h> #include <tchar.h> int _tmain(int argc, _TCHAR* argv[]) { int i=0; while(i<argc){ _tprintf(_T("%s\r\n"),argv[i++]); } return 0; } しかし上記プログラムに日本語の引数をわたすと文字化けするではないか。なでしょうか?

  • const の使い方

    お世話になります。 VC5.0からVC2005.NETにソフトの移植をしているのですが、 その際、const の使い方で混乱しております。 環境:WinXP、VC2005.NET 以下のコードをビルドするとコンパイルエラーが出てしまいます。 ネットで検索しても、混乱中の上自分のケースに当てはまっているのか どうかさえも怪しい状態でして・・・ --コード-- #include "stdafx.h" class A { public: void func( const int*& a ); }; void A::func( const int*& a ) { return; } int _tmain(int argc, _TCHAR* argv[]) { int *a; A CA; CA.func( a ); ←※ここでエラー return 0; } --ここまで-- --エラー-- error C2664: 'A::func' : 1 番目の引数を 'int *' から 'const int *&' に変換できません。(新しい機能 ; ヘルプを参照) --ここまで-- 基本的なことですがご教授願います。

  • C言語のprintfで桁数をそろえる

    次ので桁数をそろえると書いてあったけどやってみたらできなかった。 コンパイラはMS visual c++バージョンはおそらく7.1.3019 #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { int a; scanf("%d",&a); printf("a=%3d\n",a); return 0; }

  • 【C++】関数ポインタの使い方

    関数ポインタの使い方で悩んでいます。 下記の (1)のようにグローバルメソッドとして定義したメソッドを関数ポインタに代入することは出来るのですが、 (2)のようにクラスのメンバメソッドとして定義したメソッドは関数ポインタに代入することは出来ませんでした。 Error:バインドされた関数へのポインターは関数の呼び出しにのみ使用できます。 というエラーが発生します。 関数ポインタに外部参照でメソッドを代入することは出来ないのでしょうか? -----(1)------------------------------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; int f(int a, int b){ return a * b; } int _tmain(int argc, _TCHAR* argv[]) { typedef int (* FUNC_POINTER)(int, int); FUNC_POINTER fp; fp = f; cout << fp(1,2) <<endl; getchar(); return 0; } ------------------------------------------------------------------------- -----(2)------------------------------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; class MPointerList{ public: int f(int a, int b){ return a * b; } }; int _tmain(int argc, _TCHAR* argv[]) { typedef int (* FUNC_POINTER)(int, int); FUNC_POINTER fp; //fp = f; MPointerList mP; fp = mP.f; cout << fp(1,2) <<endl; getchar(); return 0; } -------------------------------------------------------------------------

  • C言語のフローチャート

    昨日に引き続き失礼します。下記のプログラムを作成したのですがフローチャートは、どのように書けばいいのでしょうか? #include "stdafx.h" #include <stdio.h> int _tmain(int argc, _TCHAR* argv[]) { char ss[10] = "abcdefg"; char *ssp; ssp =ss; while (1){ if (*ssp ==0) break; printf("文字 *ssp=%c\n",*ssp); ++ssp;} int ary[10] = {1,2,3,4,5,6,7,8,9,10}; int *pt; pt = ary; while (1) { if (*pt == 10) break; printf("値 *pt=%d\n",*pt); ++pt;} return 0; }

  • 文字配列から数値への変換

    MicrosoftのVisual-Studio 2005を使っています。 C/C++については、ほぼ素人で、困っています。 下記のような簡単なソースで、 456 012 678 を表示するようにしたいのですが、できなくて困っています。 最初の 123 789 345 は下記のソースで表記できたのですが、どうすればよいの でしょう? 数値をわざと文字列で読み込んで、これを 数値に変換しているのでややこしいのかもしれませんが、 できればこれでやりたいので、申し訳ありませんが、教えていただ けないのでしょうか。よろしくお願いします。 #include "stdafx.h" #include "stdlib.h" char str[3][200] = { "123 456", "789 012", "345 678" }; int _tmain(int argc, _TCHAR* argv[]) { int a[10]; for (argc = 0; argc < 3; argc++){ a[argc] = atof(str[argc]); printf("%d\n", a[argc]); }; return 0; }

  • main の引数には const 付けた方が

    C言語での質問です。 引数を取るような main 関数は int main( int argc, char *argv[]){~} とされていますが、argvの指す文字列を変更する、というのはいくら何でもまずいので、 int main( int argc, const char *argv[]){~} あるいは int main( int argc, const char const * const * argv){~} の方がいいのではないでしょうか? 何故、constを付けない形が出回っているのでしょうか?

  • マネージクラスについて

    マネージクラスで可変長の引数を使いたいのですが、 public ref class CTest { public: CTest(); // コンストラクタ ~CTest(); // デフォルトコンストラクタ !CTest(); // ファイナライザ Msg(PSTR str, ...); // 可変長引数 }; とすると、 「error C3269: マネージ クラスのメンバ関数は '...' と共に宣言することはできません」 というエラーがでてしまいます。 なんとかしてマネージクラスで 可変長の引数を使いたいのですが、方法がわかりません。分かる方いますでしょうか?