C++コマンド集のページ

2008.11.9 (by T. Kondo (KEK))
link to: 基礎からC++ | C++概略 | STL解説 | C++言語解説 | C++トレーニングコース(2005坂本) | C++入門@岡山 | C++/ROOT環境設定 | C++/ROOT解析チュートリアル | AJのdoxygenHP | CLHEP | CLHEPクラスリスト
ここでの項目:クラス継承コンストラクターヒストグラムSTL(テンプレート)オブジェクト入出力ポインタ関数配列コンパイル演算分岐文字列その他サンプル参考書
   
クラス : →topへ
class Car{ };base class宣言。class Car {private: double gas; public: void showGas();}; (最後に;が必要!gasはデータメンバ、showGasはメンバ関数。public指定ないとみなprivate。サンプル:Class.cc->Class.out
アクセス制御public(公開メンバー、ATLASではメンバーデータの公開を禁止していますので、基本的にメソッドのみ)。protected(継承クラスにアクセスを許す非公開メンバー)。 private(継承クラスにアクセスを許さない非公開メンバー。例えば基底クラスの中で厳重に管理されており、子クラスのメソッドから不注意に操作されたくないメンバーデータはprivateに設定する。)ATLASではクラス定義の中ではまずpublic、続いてprotected、最後にprivateメンバーを宣言する。
classメンバ関数の定義void Car::showGas() {------;}(::をスコープ解決演算子と呼ぶ。)使用例:member_function.cc
class RacingCar : public Carclassの継承:クラスCarを基底として派生クラスRacingCarを定義する。publicはCarのpublic memberはすべてRacingCarのpublicメンバになることを示す。->Class.cc
インライン関数double getGas(){return gas;}のようにクラス宣言内で関数本体を定義する。;が{}の内側に移る。
Point Point::operator+(Point p)+演算子のオーバーロード。宣言は Point operator+(Point p);。参照引数は 形式上からポインターは使えず参照のみになる(Point operator+(const Point& p);など)。
フレンド関数よるoverloard演算子の両側の型が違うとき。friend Point operator+(int a, Point p);
return *this;単項演算子のoverload(例++)で、そのメンバー関数を呼び出したオブジェクト自身へのポインタを意味する。
変換関数(conversion function)operatotr double(){return gas;}はメンバーgasをdoubleに変換する。使い方はdouble g=(double)object;。
privateメンバ-データprivateと宣言され名前はいずれもm_で始まるのはATLASのコンベンション(静的メンバーをのぞき)。ATLASではメンバーデータの公開を禁止している。m_はメンバー変数(データ)のmかな。
staticメンバーデータクラスのオブジェクトの生成・破棄と無関係に最初から最後まで存在しデータを保持し続ける。クラスに属する全てのオブジェクト値を共有される。個々のオブジェクトが作成されていなくてもアクセスできる。ATLASのコンベンションではs_始める。
テンプレートクラスいろいろな型を扱う雛形を提供する。クラステンプレートは template class XX {....}で、メンバ関数は template void XX::memberFunctuion(....)で与えられる。例:ClassTemplate.cc
クラスの継承 : →topへ
派生クラス(derived class)宣言は class RaceCar : public Car{ }; 定義は RaceCar::RaceCar(int c, double g):Car(g){...}。ここで:Car(g)の部分はbase classのconstructorにg値を渡す時に加える。 これがないとbase classのdefault constructorが使われる。constuctorの呼出順序は当然base→derived。
メンバ保護:privateとprotectedprotectedは派生クラスからアクセスできるがpublicでない。
継承時のメンバ保護public継承ならbase classのアクセス制限が通用するが、protectedやprivateで継承すると外部から base classのpublicメンバーは派生クラスに属するのでprotectedないしprivateに変化する。
メンバ関数のoverridingbaseとderived classで同じメンバー関数を定義でき、derived classのそれが優先する。しかし base classのポインターが派生クラスobjectを指してもメンバー関数はbaseの方が使われる(X->YのときはXのclassのメンバー関数が使われる)。
仮想(virtual)関数virtual void draw();などとbase classのメンバ関数にvirtualを指定しておく。ポインターが指しているobjectに応じた適切なメンバー関数が呼ばれる。
純粋仮想(pure virtual)関数virtual void showGas()=0;と関数を0で初期化した場合。一つでもこのような純粋仮想関数を持つクラスは抽象クラスと呼ばれオブジェクトを作ることが禁止されている。必ず継承したクラスを用意してそのクラスを使うこと。
抽象クラス(abstract class)純粋仮想(pure virtual)関数(virtual void showGas()=0;)を1つでも持つclass。 objectを作成できない。抽象クラスの純粋仮想関数は必ずoverridingされなくてはならない。overridingによって同じ名前の関数が さまざまな用途に使われることを多態性(polymorphism)という。 (坂本tutorial)抽象クラスは大規模フレームワークに利用者が開発した部品を組込むのに適した仕組み。組込みはフレームワークが提供する抽象クラスをベースにして自分の部品を開発する。少なくともすべての純粋仮想関数を実装しさえすれば、そのフレームワークの中で使える部品になる(この意味でこのような抽象クラスをインターフェースと呼ぶ)。Athenaはそのようなフレームワークの一つ。Athenaの中で使われるアルゴリズムやサービスはすべてインターフェースクラスを継承して作ることになる。
多重継承class Algorithm : public A, public B {...};のように2つのベースクラスを親に持つことができる。ATLASルールはメンバーデータを持ったクラスの多重継承を避ける。多重継承して良いのは、・純粋仮想関数のみを持つ。
仮想継承A→B、A→C、B→D、C→Dのような菱形継承のとき、基底クラスAのメンバーm_identifierをDで使うときはB経由かC経由を明示する(B::A::m_identifierとC::A::m_identifier)のは都合が悪い。元々m_identifierというのはオブジェクトの固有番号のつもりでつけており、Dクラスのオブジェクトも一つユニークなm_identifierを持つべきでしょう。クラスAは多重継承されても一つだけ引き継いでほしいので、仮想継承を使う。class B : virtual public A {...}; class C : virtual public A {...}; virtualに継承することにより親の親が同一の場合メンバーは一つだけ引き継ぐ。 大規模なソフトウエアシステムでは多重継承を使うことにより合理的に階層を実現することが出来ます。その場合仮想継承は重要な機能です。この節の最初の例、Algorithmも実は class Algorithm : virtual public IAlgorithm, virtual public IProperty {...}; として定義されています。
コンストラクター,   sample program:Class.cc :   →topへ
Car::Car(){gas=0;}コンストラクターCar()で定義しobjectを作ったとき初期化操作をする。引数ないものはdefault constrctorと呼ぶ。定義されてない時はcompile時にdefault constrctorが作られるが何もしない。
Car(double gas=100);
Car::Car(double g);
デフォルト引数(gas=100)を持つコンストラクターを定義すれば、 デフォルトコンストラクター(引数なし)を兼ねデフォルト引数で初期化操作をする。 しかし本体ではCar::Car(double gas){ }と=100は置かない。
Car::~Car()デストラクターはコンストラクターCar()で動的objectを作ったとき必要。
T::T(int i0):i_member(i0){ }イニシャライザーリストはコンマで切られたリストで、クラスのメンバi_memberは引数i0で初期化される。Skinner p.206,256
メンバの初期化イニシャライザー法と代入法の2つがある。constメンバは代入法は使えない。
Car(const Car& c);object copyのためのコピーコンストラクター。Car::Car(const Car& c){.......}で定義する。T(T&)で唯一の引数は参照引数でなくはならない(Skinner p.227)。 (例:CopyConstructor.cc
Car& operator=(const Car& c);object copyのための代入演算子=のオーバーロード。 Car& Car::operator=(const Car& c){.......}で定義する。(例:CopyConstructor.cc
仮想デストラクタclass Shape {... public:virtual ~Shape( );...};仮想メンバーを持ったクラスのデストラクタは必ずvirutalとすることがATLASでは要求されている。
オブジェクト :     →topへ
Car mycar;class Car のオブジェクトmycarを宣言する。
mycar.gas=25.5;mycarのデータメンバであるgasに25.5を代入する。外からはgasがpublicのときのみ有効。
mycar.setGas(27.3);publicメンバ関数setGas()を呼び出してprivateなデータメンバgasの値をセットする。
mycar.showGas();mycarのメンバ関数showGas()を呼び出す。
Car* pMycar;
pMycar= new Car;
pT = new int [n];
動的に生成されたT型オブジェクトのポインタ。newの時は必ずポインタになる! またdefault constrctorのみが呼ばれる。このような動的メモリー確保(dynamic allocation)は自分で責任持って開放すること。プログラム時に配列の大きさを決められるので 文字列などに便利。
delete p動的メモリーの解放。
(*p).x または p->xポインターpが示すオブジェクト(*p)のメンバーxを呼ぶ。->は選択(アロー)演算子と呼ぶ。
代入によるコピーa = b;のときassignment operator = をオーバーロードしておかなくれはならない。 動的objectを作る場合は明示的に指示しておかなくてはならない。
初期化によるコピーT a = b;のときはコピーコンストラクター(上記参照)が呼ばれて初期化される。
STL :STL解説,蔵重の中級入門@岡山,STLページ(日本語):   →topへ
STL(Standard Template Library)はC++標準ライブラリの中に含まれているクラス群のこと。テンプレート化されているので型を選ぶ必要がない。
std::vector動的配列をテンプレートクラスで表現したも。動的配列なのでその要素数は必要なときに自動的に変更される(専用のメンバ関数を呼び出して要素を追加していることが条件)。
コンテナデータを管理するテンプレートクラスのこと。vectorやlistのように要素が連続的に並ぶコンテナはシーケンスコンテナ。setやmapのように要素が常にソートされた状態を保つコンテナを連想コンテナと呼ぶ。
std::vector<Particle*> &AAParticle型の可変長配列(vextor)のAAをSTLのコンテナvectorで設定する。AA.push_back(a), AA.size(), AA.......などがある。->sample program vector.cc,invmass.cc
イテレータiteratorvector::iterator it = array.begin(); vector「array」のイテレータのインスタンス化:iterator.cc
入出力 :     →topへ
std::cout << "xx" << endl;xx をモニター画面(に結びついたoutput stream)に出す。endlは改行操作関数。 std::は標準名前空間を示す。
std::cerr << "xx" << endl;xx をoutput redirectionしてもモニター画面に出す。>& logならlogに行く。
std::cin >> a >> b >> c ;キーボードより入力する。  #include <iostream>
ポインタ : サンプルpointer.cc    →topへ
int *pA;pAはint変数のポインター。例:double* px=&x;。複数ならint *pa,*pbとせよ。 ポインター自身はアドレスだが型指定(int*など)が必要。int* pでもint *pでもいい。
*pAポインターpAが示すアドレスを参照する。*をindirecto operator(間接参照演算子)と呼ぶ。
pA=&a変数aのアドレス&aとpAに格納する。aと*pAは同じ変数aの値を示すことになる。
int& rA=a;参照(reference)rAを変数aで初期化する。rAはaの別名となり以後全く同じものを示す。しかし後でrA=aはできない。
関数 :   →topへ
関数名(引数リスト);関数の呼び出し。ふつう.h内でprototypeを宣言しておく。
引数のdefault値idouble Sqrt(double x, double acc = 0.01);のように引数のdefault値がある場合、呼ぶ時は省略可能a=Sqrt(a)でよい。連続した引数だけが省略可能。−> function.cc
void showNumber(int x);関数宣言(function declaration)。戻り値の型 関数名(仮引数){ }。voidは戻り値が無い場合。
void F(int x);
使うときは F(x);
値渡し(by value)でこのときは実引数が「コピーされて」渡される(仮引数という)。従ってサイズが大きいと時間かかる。また関数の中からxを変えても元のx(実引数)は変わらないので注意。参照渡しならそうでない。-->function.cc
void F(int* y);
使うときは F(&y);
参照渡し(by reference)で引数はポインターを介して渡す。実引数側はF(&y)と入れ、関数内は*yとして使う。-->function.cc
void F(int& z);
使うときは F(z);
これも参照渡し(by reference)であるが引数に参照を使う。実引数側も関数内も変数zでポインター(&zまたはpz)ではない事。-->function.cc
void F(const int& z);関数内で実引数zの値を変更を行わないことを明示。関数内で変更するとエラーになる。
void showNumber(int x=0);デフォルト引数(default argument)を使う。このとき実引数なしで呼ぶことが可能となり デフォルト値が使われる。複数の引数のときはそれより右の引数は全てデフォルト引数が指定されなければならない。
return x;xは戻り値。式でもいい。無いときはreturn;
関数のオーバーロードfunction overloading(関数の多重定義)。引数の型や数が異なる同名の関数を複数定義できる。戻り値の型 だけが異なるのはだめ。
関数テンプレート扱う型以外は全く同じ処理を行う関数はコードを一つにまとめることができる。
template <class T> T maxt(T x, T y){...........}。例:FunctionTemplate.cc
インライン関数inline 戻り値の型 関数名(引数リスト){........}。compile時に関数を呼び出すコードの位置に 関数本体を埋め込むのでプログラムが速くなる。
配列 :   →topへ
int A[3][2]={{0,2},{3,-1},{4,5}};配列の定義と初期化を同時に行った。 int A[3][2]はint A[][2]でもいい。{initializer}と呼ぶ。
配列名AはA[]の先頭番地のポインターである。*AはA[0]と同じ。2次元の場合B[][]の場合はB[]がポインターになる。
double F(int a[]);
使い方:double F(A);
配列A[]のポインターAを引数にしている。ポインター渡し。
double F(int* pA);
使い方:double F(A);
配列A[]のポインターAを引数にしている。関数の中で*(pA+i)などと使える。
このときは pA[i] と使用してもよい。ポインターpAのi個先の要素を指す。pA[2]は*(pA+2)と同じ。
ヒストグラム :   →topへ
TH1D * h_check[5];header file中でのヒストグラムh_checkの宣言文。#include <TH1.h>が必要。
h_check[0]=new TH1D(---)cxx中でのヒストグラムh_checkの定義文。
h_check[0]->Fill(p.eta());ヒストグラムh_check[0]にfillする。
コンパイル :   →topへ
g++ --versioncompiler のversionを出す。
g++ test.cxxcompile, linkをして実行ファイルa.exeを作る。
g++ -c func.cxxcompileしてobject file func.oを作る。
nm func.oオブジェクトファイル中の情報を見る。
g++ -o b.exe program.cc func.olinkして実行ファイルb.exeを作る。
ar r libl3.a func.o func4.oarはarchive。libl3.aというlibraryを作る。必ずlibXXX.aと最初にlibが必要。
g++ -o funcdemo.exe main.o -L. -ll3 -o funcdemo.exeは出力ファイル名指定。main.oがエントリーポイントです。-L.はライブラリファイルを探すパス指定(. ピリオドは現在のディレクトリ) リンカー(g++のこと)は-Lオプションで指定されているディレクトリを探す。 LD_LIBRARY_PATH環境変数が設定されているとそこに含まれているパスを順番に探す。さらに見つからなければ その言語コンパイラがインストールされた標準のライブラリのあるディレクトリ(/libや/usr/lib等)を探す。
-lオプションはライブラリファイルの指定。libXXX.aのXXXの部分を-lに続けて記述する。-ll3とあるのは-lに続くl3を 使ってlibl3.aというファイルを指定。-lmとあるとlibm.aが指定。
演算・分岐 :   →topへ
==、!=、<、>、<=、>=二項演算で、==等しいとき真、!=等しくないとき真
if(a==b)Y;else Z;if(i>10) {i = 10; j=20;}、if(a==b) k = iarray[ i ]; else k = 0;
if(a==b)Y;else Z;if(i>10) {i = 10; j=20;}、if(a==b) k = iarray[ i ]; else k = 0;
a=(a>max)?max:a;maxより大きければmaxに置き換えるー>if.cc
if(...)continue;.....loopの中で、その後に続く.....をスキップする。
switchswitch(式) {case 値1: 文; case 値2: 文.......; default: 文}
for( )文for( 初期化式; 判定式; 更新式 ) 実行文 例:for( int i = 0; i < 10; i++ )
while(式)文式を評価し、真であるかぎり文を実行する。偽であればwhile文を終了。
do 文 while(式);無条件に文を実行し、その後式を評価する。真であれば文を繰り返し 実行する。最初から式が偽であっても一度は実行される。
絶対値abs, fabsabs(int), fabs(float)であるがISO C++ には#include でusing namespace std;ならabs()はどの型にも使える->abs.cc
fmod(x,y)x/yの余りを示す。fmod(i,y),fmod(float(i),float(k))はいいがfmod(i,j)はよくない。
pow(x,2)x*xなどの累乗、冪を表す。sqrt(pow(x,2)+pow(y,2))
文字列 :   →topへ
数値ー>文字列ss<<"sample"<<i<<".dat"; cout <<ss.str()<<endl; 追加のみなのでss.clear(); または ss.str("");
文字列ー>数値#include <sstream>、stringstream ss; ss<<"3.14"; ss>>pi;
charの配列char ff[][3]={"test-0","test-1","test-2"}; その他 :   →topへ
スコープ(利用範囲)変数やオブジェクトがどの範囲まで見えるかを表したも。(1)大域(global)変数:プログラム上のいかなる場所からも見える。(2)クラスメンバーデータ:メンバー関数の定義の中から見える。ATLASではメンバー関数をm_で始める。 (3)局所変数:関数の中でのみ見える.(4)複文中の局所変数:複文(if, forなど)の中でのみ見える。 同じ名前のものが重なる場合はより内側のものが採用され、::を前につければglobal変数を示す。ATLASでは同じ名前を異なる場合に使用することは禁止。
スコープ演算子 ::派生クラスの中からBaseClassのvfuncを使いたいときはBaseClass::vfunc();
./ZZ < input.script >& loginput.script入力でZZを実行し、すべての出力をlogに出す。
i += 2i=i+2
&& || ! .and. .or. not.
double xdouble precision float型の変数 x を定義。"float" "double" "long double"がある。
const double pi=3.14定数識別子piの定義、この変数(pi)は値を変更できない。この「=」は代入演算子でなく、定数識別子とその初期値を区別しているだけ。(Skinner p.81)-->const.cc
int main(void)void識別子は引数がないことを示す。Cの流れで引数のvoidは省略できる。
void f(int n);関数fは整数引数をもつが値を返さない関数なのでvoidと書く。
キャスト演算子int id = (int)(d*pi); div=(double)n1/(double n2); などの(int), (double)を言う。
bool型変数bool型変数にはC++で追加されている予約語のtrue 及び false いずれかを代入。trueは0以外の値、falseは0。 C++のbool型は整数型と関係しているためインクリメントするとtrueになる。デクリメント -- 動作は保証されない。ここより引用。サンプルbool.cc
namespace myspace{int n;......}名前空間の宣言:myspace::n = 1002と使える。例:NameSpace.cc
using namespace myspace;名前空間のusing宣言(using directove)を使うとそれ以後は「myspace::」を省略できる。
#ifndef __MYHISTOGRAM_Hインクルードガード。もし__MYHISTOGRAM_Hが未定義ならば、#defineで__MYHISTOGRAM_Hを 定義し#endifまでを読み込む。定義済みであればそれ以降#endifまでの部分をスキップ。この仕組でクラスの定義が二度出現することを避ける。
rand()random number generation: example->random.cc
サンプルプログラム :   →topへ
Car.ccconstructor内で動的objectを作りdestructorで消する練習。 出力結果
Class.cc クラスの基本動作(overloading constructor, destructor, virtual function, 派生class, 動的object)の練習。出力結果
CopyConstructor.cc コピーコンストラクターの練習。出力結果
AbstractClass.cc 抽象クラスVehicle-->派生クラスCar, Truckの練習。出力結果
vector.ccvectorの練習
pointer.ccポインターの練習
random.ccランダム数発生
参考書 :   →topへ
高橋麻奈著「やさしいC++」第2版\2,600、出版社ソフトバンク パブリッシング。 非常に丁寧で最後はcopy constructorなどまである。初心者には打ってつけで楽しく学べる。おすすめ。
M.T.Skinner著「C++基礎講座」改定新版(1999.12)出版社インプレス、 初心者には途中から急に難しくなりすぎる。しかし「やさしいC++」をマスターした後の参考書としてはすばらい!


Send your comments on this page to kondo@kekvax.kek.jp