C,C++メモ
をテンプレートにして作成
[
トップ
|
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
C,C++,VCに関する雑多なこと
-----
#contents
-----
*C,C++ [#xdd5f045]
**出力オペレータ [#d9843a7b]
vectorや自分で作ったクラスに対して画面出力オペレータを定...
以下はvectorに関してオペレータを作成した場合の例.
#code(C){{
//! vectorの出力オペレータ
template<class T>
inline ostream &operator<<(ostream &out, const vector<T> ...
{
vector<T>::const_iterator i = x.begin();
for(; i != x.end(); ++i){
out << *i << " ";
}
return out;
}
}}
**Win32環境でのマルチスレッド [#i0cbfd38]
Win32でのスレッド生成には,
-_beginthread
-_beginthreadex
- CreateThread
などがある.CreateThread はメモリリークがあるらしい.
_beginthreadが一番簡単で,スレッドハンドルも_endthreadで...
_beginthreadexが一番安全なもよう.ただし,スレッドハンド...
以下は_beginthreadexを用いたもっとも単純な例
#code(C){{
#include <process.h>
#include <Windows.h>
// スレッド関数
unsigned int func(void *x)
{
for(int i = 0; i < 10; ++i){
cout << "thread " << *((int*)(x)) << endl;
}
_endthreadex(0);
return 0;
}
int main(void)
{
HANDLE handle;
int x = 1;
// スレッドを開始
handle = (HANDLE)_beginthreadex(NULL, 0, (unsigned int (...
for(int i = 0; i < 10; ++i){
cout << "thread 0" << endl;
}
// スレッド終了を待つ
WaitForSingleObject(handle, INFINITE);
// ハンドルを閉じる
CloseHandle(handle);
return 0;
}
}}
**メンバ関数ポインタ [#y555b7a2]
クラスのメンバ関数を関数ポインタを使って扱う方法.~
例えば,以下のようなクラスがあるとする.
#code(C){{
class FuncPtrTest
{
public:
void Func1(int i){ cout << i << endl; }
void Func2(int i){ cout << 2*i << endl; }
};
}}
メンバ関数ポインタ変数は,
void (FuncPtrTest::*pFunc)(int) = &FuncPtrTest::Func1;
のようにしてとることができる.
typedefで関数を定義する場合は以下.
typedef void (FuncPtrTest::*FUNC)(int);
***オペレータ"->*",".*"を用いた呼び出し [#q8c080c3]
呼び出す場合は,
FuncPtrTest *pFuncClass = new FuncPtrTest;
(pFuncClass->*pFunc)(1);
となる.ポインタでないクラスオブジェクトを用いる場合は以...
FuncPtrTest funcClass;
(funcClass.*pFunc)(1);
typedefした場合は以下.
FUNC defFunc = &FuncPtrTest::Func2;
(pFuncClass->*defFunc)(8);
メンバ関数内から呼び出す場合はthisポインタを用いる.
#code(C){{
class FuncPtrTest
{
public:
void Func1(int i){ cout << i << endl; }
void Func2(int i){ cout << 2*i << endl; }
void Test(void (FuncPtrTest::*func)(int));
};
void FuncPtrTest::Test(void (FuncPtrTest::*func)(int))
{
(this->*func)(2);
}
void main(void)
{
void (FuncPtrTest::*pFunc)(int) = &FuncPtrTest::Func2;
FuncPtrTest *pFuncClass = new FuncPtrTest;
pFuncClass->Test(pFunc);
delete pFuncClass;
}
}}
***テンプレートを用いた呼び出し [#i62ee63a]
テンプレート関数を用いることでもクラスオブジェクトを指定...
#code(C){{
template<FuncPtrTest* P>
void FuncT(int i)
{
P->Func1(i);
}
FuncPtrTest g_FuncClass;
void main(void)
{
FuncT<&g_FuncClass>(8);
}
}}
ただし,テンプレートに指定するクラスオブジェクトはグロー...
***boost::bindを用いた呼び出し [#tfc59dce]
boost::bindを用いることで,通常の関数ポインタとメンバ関数...
区別なくboost::functionとして扱うことができる.
まず,boost::functionを用いて関数を定義する.
#include <boost/bind.hpp>
#include <boost/function.hpp>
void TestBind(boost::function<void (int)> func)
{
func(16);
}
関数の呼び出しでは,bindを用いてクラスオブジェクトを指定...
FuncPtrTest *pFuncClass = new FuncPtrTest;
TestBind(boost::bind(&FuncPtrTest::Func2, boost::ref(pFu...
***コード例 [#ge65583a]
#code(C){{
#include <boost/bind.hpp>
#include <boost/function.hpp>
class FuncPtrTest;
typedef void (FuncPtrTest::*FUNC)(int);
class FuncPtrTest
{
public:
void Func1(int i){ cout << i << endl; }
void Func2(int i){ cout << 2*i << endl; }
void Test(void (FuncPtrTest::*func)(int));
};
void FuncPtrTest::Test(void (FuncPtrTest::*func)(int))
{
(this->*func)(2);
}
template<FuncPtrTest* P>
void FuncT(int i)
{
P->Func1(i);
}
void TestBind(boost::function<void (int)> func)
{
func(16);
}
FuncPtrTest g_FuncClass;
void main(void)
{
FuncPtrTest *pFuncClass = new FuncPtrTest;
void (FuncPtrTest::*pFunc)(int) = &FuncPtrTest::Func1;
(pFuncClass->*pFunc)(1);
pFunc = &FuncPtrTest::Func2;
(pFuncClass->*pFunc)(1);
pFuncClass->Test(pFunc);
FuncT<&g_FuncClass>(8);
FUNC defFunc = &FuncPtrTest::Func2;
(pFuncClass->*defFunc)(8);
TestBind(boost::bind(&FuncPtrTest::Func2, boost::ref(pFu...
delete pFuncClass;
}
}}
実行結果
1
2
4
8
16
32
**ビット演算 [#n5f4764b]
|演算の種類|演算子|使用例|h
|論理積(AND)| & | x & y, x &= 0x01 |
|論理和(OR)| | | x | y, x |= 0x01 |
|否定(NOT)| ~ | y = ~x; |
|排他的論理和(XOR)| ^ | y ^ x; y ^= x; |
|右シフト| >> | y = x >> 2; |
|左シフト| << | y = x << 2; |
実行例
1011&0101 = 0001
1011|0101 = 1111
~1011 = 0100
1011^0101 = 1110
1011>>2 = 0010
1011<<2 = 1100
**メンバ関数テンプレート [#s362c3d2]
#code(C){{
class rxTemplateTest2
{
Type data;
public:
rxTemplateTest2();
~rxTemplateTest2(){};
template<typename T>
void InlineFunc(Type x)
{
data = x;
}
template<typename T>
void Func(Type y);
};
template<typename Type>
void rxTemplateTest2::Func(Type y)
{
data = y;
cout << data << endl;
}
}}
**テンプレートクラス [#v0bbb37d]
#code(C){{
template<class Type>
class rxTemplateTest
{
Type data;
public:
rxTemplateTest();
~rxTemplateTest(){};
void InlineFunc(Type x)
{
data = x;
}
void Func(Type y);
};
template<class Type>
rxTemplateTest<Type>::rxTemplateTest()
{
data = 0;
}
template<class Type>
void rxTemplateTest<Type>::Func(Type y)
{
data = y;
cout << data << endl;
}
}}
Visual C++だとテンプレートクラスの実装をcppファイルに書くと
テンプレートクラスを実体化できない設計になっている(inclus...
基本的にはヘッダにすべての実装を書くこと.
どうしてもcppファイルに書きたい場合は,テンプレートクラス...
上記の例だと,
#code(C){{
#include "template_test.h"
template<class Type>
rxTemplateTest<Type>::rxTemplateTest()
{
data = 0;
}
template<class Type>
void rxTemplateTest<Type>::Func(Type y)
{
data = y;
cout << data << endl;
}
template class rxTemplateTest<int>;
template class rxTemplateTest<float>;
}}
**プリプロセッサ [#od0f1b15]
コンパイル前にソースに対して行われる前処理のこと.
C言語のプリプロセッサ命令(ディレクティブ)には"#"が頭に付...
***#include [#oc33c1c6]
ヘッダファイルの読み込み
#include <stdio.h>
#include "vec.h"
基本的にはシステムで用意されているヘッダは<>で囲み,
自分で作成したヘッダを""で囲む.
***#define [#za309753]
マクロ置換.数値や文字列などの定数として扱える.
#define 定数名 置換後の数値や文字列
例えば,
#define PI 3.14159265358979323846
#define GRAVITY 9.80665
#define FILENAME "test.dat"
マクロ関数として関数も定義できる.
#define AREA(r) (r*r*PI)
#define MAX(a, b) ((a > b) ? a : b)
#define FEQ(a, b) (fabs(a-b) < 1e-8)
***複数行にわたるマクロ [#t87164bd]
マクロは基本的に1行に書かなければならないが,複数行にどう...
#define RXFOR2(i0, i1, j0, j1) for(int i = i0; i < i1; +...
for(int j = j0; j < j...
#define RXFOR3(i0, i1, j0, j1, k0, k1) for(int i = i0; i...
for(int j = j...
for(int k...
のように"\"を行末に付ける."\"の後には何も書かないこと(コ...
***#undef [#b6530271]
#defineで定義した記号定数,マクロ関数などを無効にする.
#undef PI
***#if 〜 #else 〜 #endif [#d0e42b3d]
if文と同じようなもの.
#if 式1
処理1
#elif 式2
処理2
#else
処理3
#endif
式には0や1などの数値を直接指定したり,
defined()でマクロ定義されているかどうかの判別などを指定で...
#if defined(DEF)
#endif
否定"!"も使える
#if !defined(DEF)
#endif
式にはC言語で使えるものはほとんど使える(==や<,<=,&&,||など)
また,#ifdefを使えば,#if defined()と同じとなる
#ifdef DEF
#endif
否定の場合は
#ifndef DEF
#endif
***既定義マクロ [#q4b0bf33]
コンパイラによって事前に定義されているマクロがいくつかあ...
-__FILE__ : コンパイルしているファイル名
-__LINE__ : コンパイルしている行の行番号
-__DATE__ : 現在の日付
-__TIME__ : 現在の時間
-__STDC__ : コンパイラが規格に準拠しているかどうか.準拠...
Visual Studio 2005の場合,プロジェクトのプロパティから「C...
「はい」にすれば定義される.
***マクロ置き換え演算子"#","##" [#z8a0ae1a]
-# : マクロ実引数を文字列化する.
#define str(x) #x
char *xyz = "abc";
printf("%s\n", xyz);
printf("%s\n", str(xyz));
表示は
abc
xyz
となる.
-## : 前後の句を結合
#define add(x, y) data##x + data##y
int data1, data2;
add(1, 2); // data1 + data2
**プリプロセッサによるインクルードガード [#c98802a3]
ヘッダファイルなどが複数回読み込まれるのを防ぐのに#ifndef...
#ifndef _HEADER_H_
#define _HEADER_H_
ヘッダの内容
#endif // _HEADER_H_
"_HEADER_H_"はヘッダファイルごとにユニークなものを用いる.
**C言語からC++のヘッダを読み込む [#m1104f59]
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
**入出力ストリームの書式指定 [#c9f8ca9c]
C++の入出力ストリームは変数の方を気にせずに使えるので便利...
小数点以下の表示制度などを操作したい場合などもある.
そのときに使えるのがマニピュレータ.
#include <iomanip>
マニピュレータの一覧は以下.
(using namespace std; にしていることを前提として記述)
|マニピュレータ|説明|使用例|h
|endl|改行してバッファをフラッシュ| cout << "Hello world!...
|flush|バッファのフラッシュのみ| cout << "Hello world!" <...
|ends|文字列の終端文字'\0'を出力| cout << ends; |
|ws|空白文字を飛ばす入力| cin >> ws >> str; |
|oct,dec,hex|それぞれ8,10,16進数で入出力| cout << hex << ...
|setw|値の入出力幅指定| cout << setw(5) << x << endl; /* ...
|left,right|値を左寄せ,右寄せで出力| cout << setw(5) << l...
|setfill|出力幅に満たない部分を埋める文字を指定| cout << ...
また,cout,cinにはメンバ関数setf(), unsetf()があり,これ...
|引数|説明|h
|ios::skipws,ios::noskipws|先頭の空白文字を飛ばすかどうか|
|ios::unitbuf,ios::nounitbuf|出力処理のたびにバッファをフ...
|ios::dec,ios::hex,ios::oct|それぞれ8,10,16進数で入出力|
|ios::showbase|0xなどの基数表示|
|ios::fixed|10進表記法(浮動小数点数)|
|ios::scientific|指数表記法(浮動小数点数),1.0e-3など|
|ios::showpoint|小数点を常に表示|
|ios::showpos|正の符号も付ける|
|ios::uppercase|16進表記のアルファベットを大文字に|
|ios::left,ios::right|左寄せ,右寄せ|
|ios::internal|符号を左寄せ,値を右寄せで表示|
|ios::boolalpha|bool型の出力に"true","false"を使用|
引数は"|"で結合できる.
そのほか,coutのメンバ関数を用いた書式指定としては,
-width : 最小出力幅指定
cout.width(10);
-precision : 精度指定(数値全体の桁数を指定)
cout.precision(10);
-form : printfと同じような書式指定
cout.form("i = %d, x = %f\n", i, x);
**スリープ [#d738cf2c]
-Linux
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
secondsにスリープする時間を秒単位で指定する.
指定された時間スリープしたら0を返し,割り込まれた場合など...
[[Manpage of sleep:http://www.linux.or.jp/JM/html/LDP_man...
#include <unistd.h>
int usleep(useconds_t usec);
usecにスリープする時間をマイクロ秒単位で指定する.
指定された時間スリープしたら0,エラーなどがあったときは-1...
[[Manpage of usleep:http://www.linux.or.jp/JM/html/LDP_ma...
-Windows
#include <windows.h>
void Sleep(DWORD dwMilliseconds);
dwMillisecondsはスリープする時間をミリ秒単位で指定する.
-標準ライブラリで~
[[http://www.bohyoh.com/CandCPP/FAQ/FAQ00071.html]]を参考.
#code(C){{
#include <time.h>
int sleep(unsigned long x)
{
clock_t s = clock();
clock_t c;
do{
if((c = clock()) == (clock_t)-1){
return 0;
}
}while(1000UL*(c-s)/CLOCKS_PER_SEC <= x);
return 1;
}
}}
ただし,マルチタスク系のOSではCPU使用率が100%になって他の...
**時間計測 [#x9827798]
-標準ライブラリ(ANSI C)
clockを用いる.精度はCPU時間であるが,実際には1/100秒ぐら...
#code(C){{
#include <time.h>
}}
とインクルードして,
#code(C){{
clock_t t1, t2;
t1 = clock();
// 処理
t2 = clock();
printf("%f [sec]\n", (double)(t2-t1)/CLOCKS_PER_SEC);
}}
-Linux
gettimeofdayを用いる.
#code(C){{
#include <sys/time.h>
double gettimeofday_sec(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec*1e-6;
}
int main(void)
{
double t1, t2;
t1 = gettimeofday_sec(void);
// 処理
t2 = gettimeofday_sec(void);
printf("%f [sec]\n", t2-t1);
return 0;
}
}}
もしくは,getrusageを用いる.
#code(C){{
#include <sys/time.h>
#include <sys/resource.h>
double getrusage_sec(void)
{
struct rusage r;
struct timeval tv;
getrusage(RUSAGE_SELF, &r);
tv = r.ru_utime;
return tv.tv_sec + tv.tv_usec*1e-6;
}
}}
-Windows
Windowsでの時間計測には,GetTickCountやtimeGetTimeなどが...
#code(C){{
#include <windows.h>
int main(void)
{
DWORD t1, t2;
t1 = GetTickCount();
// 処理
t2 = GetTickCount();
printf("%d [msec]\n", t2-t1);
return 0;
}
}}
GetTickCount()はWindowsが起動してからの時間をミリ秒単位で...
精度的には10-20msぐらいのようである.
さらに精度が必要なときは,timeGetTimeを用いる.
#code(C){{
#pragma comment (lib, "winmm.lib")
#include <mmsystem.h>
int main(void)
{
DWORD t1, t2;
t1 = timeGetTime();
// 処理
t2 = timeGetTime();
printf("%d [msec]\n", t2-t1);
return 0;
}
}}
winmm.libをリンクしている.精度は1-2msぐらい.
マイクロ秒単位での精度が必要な場合はさらにQueryPerformanc...
#code(C){{
#include <windows.h>
int main(void)
{
LARGE_INTEGER t1, t2;
LARGE_INTEGER f;
QueryPerformanceFrequency((LARGE_INTEGER*)&f); // 高分解...
QueryPerformanceCounter((LARGE_INTEGER*)&t1);
// 処理
QueryPerformanceCounter((LARGE_INTEGER*)&t2);
printf("%f [sec]\n", (double)(t2.QuadPart-t1.QuadPart)/(...
return 0;
}
}}
システムに高分解能パフォーマンスカウンタがあれば,それに...
なければ,各関数は変数に0を格納して返す.
Windows上では最も高分解能が得られる方法の一つではあるが,...
QueryPerformanceFrequencyの値を一度見ておいた方がよいかも...
(CPUクロックが使われていたらならば,分解能は高いがクロッ...
**std::string で CString::Format や printf のように文字列...
std::ostringstream を使用.
#include <sstream>
#include <string>
std::ostringstream stream;
stream << "step : " << i;
std::string str = stream.str();
**RTTI [#a177487e]
RTTI(run-time type identification)は日本語では,実行時型...
最新のANSI C++ではサポートされているので,
#include <typeinfo.h>
として,
int x = 10;
cout << "type : " << typeid(x).name() << endl;
や
int x = 10;
if(typeid(int) == typeid(x)){
xがint型だったときの処理
}
という風に使える.
このRTTIは,クラスのポリモーフィズム(多態性)を使うときに...
**GLUTなどでDOS窓を出さない [#x524a6a7]
#pragma comment(linker, "/subsystem:\"windows\" /entry:\...
**複数モニタの検出 - Platform SDK GDI [#pb6f330b]
#include <windows.h>
EnumDisplayMonitors(...);
GetMonitorInfo(...);
など
[[MSDN:http://msdn.microsoft.com/library/ja/default.asp?u...
終了行:
C,C++,VCに関する雑多なこと
-----
#contents
-----
*C,C++ [#xdd5f045]
**出力オペレータ [#d9843a7b]
vectorや自分で作ったクラスに対して画面出力オペレータを定...
以下はvectorに関してオペレータを作成した場合の例.
#code(C){{
//! vectorの出力オペレータ
template<class T>
inline ostream &operator<<(ostream &out, const vector<T> ...
{
vector<T>::const_iterator i = x.begin();
for(; i != x.end(); ++i){
out << *i << " ";
}
return out;
}
}}
**Win32環境でのマルチスレッド [#i0cbfd38]
Win32でのスレッド生成には,
-_beginthread
-_beginthreadex
- CreateThread
などがある.CreateThread はメモリリークがあるらしい.
_beginthreadが一番簡単で,スレッドハンドルも_endthreadで...
_beginthreadexが一番安全なもよう.ただし,スレッドハンド...
以下は_beginthreadexを用いたもっとも単純な例
#code(C){{
#include <process.h>
#include <Windows.h>
// スレッド関数
unsigned int func(void *x)
{
for(int i = 0; i < 10; ++i){
cout << "thread " << *((int*)(x)) << endl;
}
_endthreadex(0);
return 0;
}
int main(void)
{
HANDLE handle;
int x = 1;
// スレッドを開始
handle = (HANDLE)_beginthreadex(NULL, 0, (unsigned int (...
for(int i = 0; i < 10; ++i){
cout << "thread 0" << endl;
}
// スレッド終了を待つ
WaitForSingleObject(handle, INFINITE);
// ハンドルを閉じる
CloseHandle(handle);
return 0;
}
}}
**メンバ関数ポインタ [#y555b7a2]
クラスのメンバ関数を関数ポインタを使って扱う方法.~
例えば,以下のようなクラスがあるとする.
#code(C){{
class FuncPtrTest
{
public:
void Func1(int i){ cout << i << endl; }
void Func2(int i){ cout << 2*i << endl; }
};
}}
メンバ関数ポインタ変数は,
void (FuncPtrTest::*pFunc)(int) = &FuncPtrTest::Func1;
のようにしてとることができる.
typedefで関数を定義する場合は以下.
typedef void (FuncPtrTest::*FUNC)(int);
***オペレータ"->*",".*"を用いた呼び出し [#q8c080c3]
呼び出す場合は,
FuncPtrTest *pFuncClass = new FuncPtrTest;
(pFuncClass->*pFunc)(1);
となる.ポインタでないクラスオブジェクトを用いる場合は以...
FuncPtrTest funcClass;
(funcClass.*pFunc)(1);
typedefした場合は以下.
FUNC defFunc = &FuncPtrTest::Func2;
(pFuncClass->*defFunc)(8);
メンバ関数内から呼び出す場合はthisポインタを用いる.
#code(C){{
class FuncPtrTest
{
public:
void Func1(int i){ cout << i << endl; }
void Func2(int i){ cout << 2*i << endl; }
void Test(void (FuncPtrTest::*func)(int));
};
void FuncPtrTest::Test(void (FuncPtrTest::*func)(int))
{
(this->*func)(2);
}
void main(void)
{
void (FuncPtrTest::*pFunc)(int) = &FuncPtrTest::Func2;
FuncPtrTest *pFuncClass = new FuncPtrTest;
pFuncClass->Test(pFunc);
delete pFuncClass;
}
}}
***テンプレートを用いた呼び出し [#i62ee63a]
テンプレート関数を用いることでもクラスオブジェクトを指定...
#code(C){{
template<FuncPtrTest* P>
void FuncT(int i)
{
P->Func1(i);
}
FuncPtrTest g_FuncClass;
void main(void)
{
FuncT<&g_FuncClass>(8);
}
}}
ただし,テンプレートに指定するクラスオブジェクトはグロー...
***boost::bindを用いた呼び出し [#tfc59dce]
boost::bindを用いることで,通常の関数ポインタとメンバ関数...
区別なくboost::functionとして扱うことができる.
まず,boost::functionを用いて関数を定義する.
#include <boost/bind.hpp>
#include <boost/function.hpp>
void TestBind(boost::function<void (int)> func)
{
func(16);
}
関数の呼び出しでは,bindを用いてクラスオブジェクトを指定...
FuncPtrTest *pFuncClass = new FuncPtrTest;
TestBind(boost::bind(&FuncPtrTest::Func2, boost::ref(pFu...
***コード例 [#ge65583a]
#code(C){{
#include <boost/bind.hpp>
#include <boost/function.hpp>
class FuncPtrTest;
typedef void (FuncPtrTest::*FUNC)(int);
class FuncPtrTest
{
public:
void Func1(int i){ cout << i << endl; }
void Func2(int i){ cout << 2*i << endl; }
void Test(void (FuncPtrTest::*func)(int));
};
void FuncPtrTest::Test(void (FuncPtrTest::*func)(int))
{
(this->*func)(2);
}
template<FuncPtrTest* P>
void FuncT(int i)
{
P->Func1(i);
}
void TestBind(boost::function<void (int)> func)
{
func(16);
}
FuncPtrTest g_FuncClass;
void main(void)
{
FuncPtrTest *pFuncClass = new FuncPtrTest;
void (FuncPtrTest::*pFunc)(int) = &FuncPtrTest::Func1;
(pFuncClass->*pFunc)(1);
pFunc = &FuncPtrTest::Func2;
(pFuncClass->*pFunc)(1);
pFuncClass->Test(pFunc);
FuncT<&g_FuncClass>(8);
FUNC defFunc = &FuncPtrTest::Func2;
(pFuncClass->*defFunc)(8);
TestBind(boost::bind(&FuncPtrTest::Func2, boost::ref(pFu...
delete pFuncClass;
}
}}
実行結果
1
2
4
8
16
32
**ビット演算 [#n5f4764b]
|演算の種類|演算子|使用例|h
|論理積(AND)| & | x & y, x &= 0x01 |
|論理和(OR)| | | x | y, x |= 0x01 |
|否定(NOT)| ~ | y = ~x; |
|排他的論理和(XOR)| ^ | y ^ x; y ^= x; |
|右シフト| >> | y = x >> 2; |
|左シフト| << | y = x << 2; |
実行例
1011&0101 = 0001
1011|0101 = 1111
~1011 = 0100
1011^0101 = 1110
1011>>2 = 0010
1011<<2 = 1100
**メンバ関数テンプレート [#s362c3d2]
#code(C){{
class rxTemplateTest2
{
Type data;
public:
rxTemplateTest2();
~rxTemplateTest2(){};
template<typename T>
void InlineFunc(Type x)
{
data = x;
}
template<typename T>
void Func(Type y);
};
template<typename Type>
void rxTemplateTest2::Func(Type y)
{
data = y;
cout << data << endl;
}
}}
**テンプレートクラス [#v0bbb37d]
#code(C){{
template<class Type>
class rxTemplateTest
{
Type data;
public:
rxTemplateTest();
~rxTemplateTest(){};
void InlineFunc(Type x)
{
data = x;
}
void Func(Type y);
};
template<class Type>
rxTemplateTest<Type>::rxTemplateTest()
{
data = 0;
}
template<class Type>
void rxTemplateTest<Type>::Func(Type y)
{
data = y;
cout << data << endl;
}
}}
Visual C++だとテンプレートクラスの実装をcppファイルに書くと
テンプレートクラスを実体化できない設計になっている(inclus...
基本的にはヘッダにすべての実装を書くこと.
どうしてもcppファイルに書きたい場合は,テンプレートクラス...
上記の例だと,
#code(C){{
#include "template_test.h"
template<class Type>
rxTemplateTest<Type>::rxTemplateTest()
{
data = 0;
}
template<class Type>
void rxTemplateTest<Type>::Func(Type y)
{
data = y;
cout << data << endl;
}
template class rxTemplateTest<int>;
template class rxTemplateTest<float>;
}}
**プリプロセッサ [#od0f1b15]
コンパイル前にソースに対して行われる前処理のこと.
C言語のプリプロセッサ命令(ディレクティブ)には"#"が頭に付...
***#include [#oc33c1c6]
ヘッダファイルの読み込み
#include <stdio.h>
#include "vec.h"
基本的にはシステムで用意されているヘッダは<>で囲み,
自分で作成したヘッダを""で囲む.
***#define [#za309753]
マクロ置換.数値や文字列などの定数として扱える.
#define 定数名 置換後の数値や文字列
例えば,
#define PI 3.14159265358979323846
#define GRAVITY 9.80665
#define FILENAME "test.dat"
マクロ関数として関数も定義できる.
#define AREA(r) (r*r*PI)
#define MAX(a, b) ((a > b) ? a : b)
#define FEQ(a, b) (fabs(a-b) < 1e-8)
***複数行にわたるマクロ [#t87164bd]
マクロは基本的に1行に書かなければならないが,複数行にどう...
#define RXFOR2(i0, i1, j0, j1) for(int i = i0; i < i1; +...
for(int j = j0; j < j...
#define RXFOR3(i0, i1, j0, j1, k0, k1) for(int i = i0; i...
for(int j = j...
for(int k...
のように"\"を行末に付ける."\"の後には何も書かないこと(コ...
***#undef [#b6530271]
#defineで定義した記号定数,マクロ関数などを無効にする.
#undef PI
***#if 〜 #else 〜 #endif [#d0e42b3d]
if文と同じようなもの.
#if 式1
処理1
#elif 式2
処理2
#else
処理3
#endif
式には0や1などの数値を直接指定したり,
defined()でマクロ定義されているかどうかの判別などを指定で...
#if defined(DEF)
#endif
否定"!"も使える
#if !defined(DEF)
#endif
式にはC言語で使えるものはほとんど使える(==や<,<=,&&,||など)
また,#ifdefを使えば,#if defined()と同じとなる
#ifdef DEF
#endif
否定の場合は
#ifndef DEF
#endif
***既定義マクロ [#q4b0bf33]
コンパイラによって事前に定義されているマクロがいくつかあ...
-__FILE__ : コンパイルしているファイル名
-__LINE__ : コンパイルしている行の行番号
-__DATE__ : 現在の日付
-__TIME__ : 現在の時間
-__STDC__ : コンパイラが規格に準拠しているかどうか.準拠...
Visual Studio 2005の場合,プロジェクトのプロパティから「C...
「はい」にすれば定義される.
***マクロ置き換え演算子"#","##" [#z8a0ae1a]
-# : マクロ実引数を文字列化する.
#define str(x) #x
char *xyz = "abc";
printf("%s\n", xyz);
printf("%s\n", str(xyz));
表示は
abc
xyz
となる.
-## : 前後の句を結合
#define add(x, y) data##x + data##y
int data1, data2;
add(1, 2); // data1 + data2
**プリプロセッサによるインクルードガード [#c98802a3]
ヘッダファイルなどが複数回読み込まれるのを防ぐのに#ifndef...
#ifndef _HEADER_H_
#define _HEADER_H_
ヘッダの内容
#endif // _HEADER_H_
"_HEADER_H_"はヘッダファイルごとにユニークなものを用いる.
**C言語からC++のヘッダを読み込む [#m1104f59]
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
**入出力ストリームの書式指定 [#c9f8ca9c]
C++の入出力ストリームは変数の方を気にせずに使えるので便利...
小数点以下の表示制度などを操作したい場合などもある.
そのときに使えるのがマニピュレータ.
#include <iomanip>
マニピュレータの一覧は以下.
(using namespace std; にしていることを前提として記述)
|マニピュレータ|説明|使用例|h
|endl|改行してバッファをフラッシュ| cout << "Hello world!...
|flush|バッファのフラッシュのみ| cout << "Hello world!" <...
|ends|文字列の終端文字'\0'を出力| cout << ends; |
|ws|空白文字を飛ばす入力| cin >> ws >> str; |
|oct,dec,hex|それぞれ8,10,16進数で入出力| cout << hex << ...
|setw|値の入出力幅指定| cout << setw(5) << x << endl; /* ...
|left,right|値を左寄せ,右寄せで出力| cout << setw(5) << l...
|setfill|出力幅に満たない部分を埋める文字を指定| cout << ...
また,cout,cinにはメンバ関数setf(), unsetf()があり,これ...
|引数|説明|h
|ios::skipws,ios::noskipws|先頭の空白文字を飛ばすかどうか|
|ios::unitbuf,ios::nounitbuf|出力処理のたびにバッファをフ...
|ios::dec,ios::hex,ios::oct|それぞれ8,10,16進数で入出力|
|ios::showbase|0xなどの基数表示|
|ios::fixed|10進表記法(浮動小数点数)|
|ios::scientific|指数表記法(浮動小数点数),1.0e-3など|
|ios::showpoint|小数点を常に表示|
|ios::showpos|正の符号も付ける|
|ios::uppercase|16進表記のアルファベットを大文字に|
|ios::left,ios::right|左寄せ,右寄せ|
|ios::internal|符号を左寄せ,値を右寄せで表示|
|ios::boolalpha|bool型の出力に"true","false"を使用|
引数は"|"で結合できる.
そのほか,coutのメンバ関数を用いた書式指定としては,
-width : 最小出力幅指定
cout.width(10);
-precision : 精度指定(数値全体の桁数を指定)
cout.precision(10);
-form : printfと同じような書式指定
cout.form("i = %d, x = %f\n", i, x);
**スリープ [#d738cf2c]
-Linux
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
secondsにスリープする時間を秒単位で指定する.
指定された時間スリープしたら0を返し,割り込まれた場合など...
[[Manpage of sleep:http://www.linux.or.jp/JM/html/LDP_man...
#include <unistd.h>
int usleep(useconds_t usec);
usecにスリープする時間をマイクロ秒単位で指定する.
指定された時間スリープしたら0,エラーなどがあったときは-1...
[[Manpage of usleep:http://www.linux.or.jp/JM/html/LDP_ma...
-Windows
#include <windows.h>
void Sleep(DWORD dwMilliseconds);
dwMillisecondsはスリープする時間をミリ秒単位で指定する.
-標準ライブラリで~
[[http://www.bohyoh.com/CandCPP/FAQ/FAQ00071.html]]を参考.
#code(C){{
#include <time.h>
int sleep(unsigned long x)
{
clock_t s = clock();
clock_t c;
do{
if((c = clock()) == (clock_t)-1){
return 0;
}
}while(1000UL*(c-s)/CLOCKS_PER_SEC <= x);
return 1;
}
}}
ただし,マルチタスク系のOSではCPU使用率が100%になって他の...
**時間計測 [#x9827798]
-標準ライブラリ(ANSI C)
clockを用いる.精度はCPU時間であるが,実際には1/100秒ぐら...
#code(C){{
#include <time.h>
}}
とインクルードして,
#code(C){{
clock_t t1, t2;
t1 = clock();
// 処理
t2 = clock();
printf("%f [sec]\n", (double)(t2-t1)/CLOCKS_PER_SEC);
}}
-Linux
gettimeofdayを用いる.
#code(C){{
#include <sys/time.h>
double gettimeofday_sec(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec*1e-6;
}
int main(void)
{
double t1, t2;
t1 = gettimeofday_sec(void);
// 処理
t2 = gettimeofday_sec(void);
printf("%f [sec]\n", t2-t1);
return 0;
}
}}
もしくは,getrusageを用いる.
#code(C){{
#include <sys/time.h>
#include <sys/resource.h>
double getrusage_sec(void)
{
struct rusage r;
struct timeval tv;
getrusage(RUSAGE_SELF, &r);
tv = r.ru_utime;
return tv.tv_sec + tv.tv_usec*1e-6;
}
}}
-Windows
Windowsでの時間計測には,GetTickCountやtimeGetTimeなどが...
#code(C){{
#include <windows.h>
int main(void)
{
DWORD t1, t2;
t1 = GetTickCount();
// 処理
t2 = GetTickCount();
printf("%d [msec]\n", t2-t1);
return 0;
}
}}
GetTickCount()はWindowsが起動してからの時間をミリ秒単位で...
精度的には10-20msぐらいのようである.
さらに精度が必要なときは,timeGetTimeを用いる.
#code(C){{
#pragma comment (lib, "winmm.lib")
#include <mmsystem.h>
int main(void)
{
DWORD t1, t2;
t1 = timeGetTime();
// 処理
t2 = timeGetTime();
printf("%d [msec]\n", t2-t1);
return 0;
}
}}
winmm.libをリンクしている.精度は1-2msぐらい.
マイクロ秒単位での精度が必要な場合はさらにQueryPerformanc...
#code(C){{
#include <windows.h>
int main(void)
{
LARGE_INTEGER t1, t2;
LARGE_INTEGER f;
QueryPerformanceFrequency((LARGE_INTEGER*)&f); // 高分解...
QueryPerformanceCounter((LARGE_INTEGER*)&t1);
// 処理
QueryPerformanceCounter((LARGE_INTEGER*)&t2);
printf("%f [sec]\n", (double)(t2.QuadPart-t1.QuadPart)/(...
return 0;
}
}}
システムに高分解能パフォーマンスカウンタがあれば,それに...
なければ,各関数は変数に0を格納して返す.
Windows上では最も高分解能が得られる方法の一つではあるが,...
QueryPerformanceFrequencyの値を一度見ておいた方がよいかも...
(CPUクロックが使われていたらならば,分解能は高いがクロッ...
**std::string で CString::Format や printf のように文字列...
std::ostringstream を使用.
#include <sstream>
#include <string>
std::ostringstream stream;
stream << "step : " << i;
std::string str = stream.str();
**RTTI [#a177487e]
RTTI(run-time type identification)は日本語では,実行時型...
最新のANSI C++ではサポートされているので,
#include <typeinfo.h>
として,
int x = 10;
cout << "type : " << typeid(x).name() << endl;
や
int x = 10;
if(typeid(int) == typeid(x)){
xがint型だったときの処理
}
という風に使える.
このRTTIは,クラスのポリモーフィズム(多態性)を使うときに...
**GLUTなどでDOS窓を出さない [#x524a6a7]
#pragma comment(linker, "/subsystem:\"windows\" /entry:\...
**複数モニタの検出 - Platform SDK GDI [#pb6f330b]
#include <windows.h>
EnumDisplayMonitors(...);
GetMonitorInfo(...);
など
[[MSDN:http://msdn.microsoft.com/library/ja/default.asp?u...
ページ名: