ATLAS日本基礎ネットワーク C++トレーニングコース
ここでの目標
目次
C++で作業するための環境をまず確認しましょう。
ATLASでのデータ解析を想定しているので、次のような環境を前提としています。
自分が使えるOSやコンパイラを確認しましょう。
/usr/bin/g++
と表示されましたか。
g++ --version
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
GCCが使えることがわかりました。次に作業をするための場所を用意しましょう。
この文書ではキーボード入力する部分を赤字で、計算機がそれに対して表示する部分を
青字
で表示しています。プログラムソースは緑字で表示されます。
現在、ホームディレクトリ(ログインした最初にいるディレクトリ)にいます。
$HOME/tutorial/cplusplus/l1 を作業場所として選びました。
早速ですからお約束のHello, World!をやりましょう。テキストエディタを起動してソースコードを書きましょう。ファイル名はhello.cxxとしましょう。
#include <iostream> main() { using namespace std; cout << "Hello, World!" << endl; }
テキストエディタを終了して、ファイルが出来ていることを確認します。
ls
hello.cxx
ではここでコンパイルします。
g++ hello.cxx
問題なくコンパイルされたでしょうか。
ls
a.out hello.cxx
うまくいくとa.outというファイルが出来ているはずです。実行してみましょう。
./a.out
Hello, World!
期待通りになりました。./a.outという表現は、このディレクトリ(.
)にあるa.out
というファイルを実行するという意味です。
それではソースコードを見ていきましょう。
#include <iostream>
この行は、第一コラムが#
ですので、プリプロセッサが解読する命令と言うことになります。include
ですから、iostream
というファイルを読み込もうと言うことを示しています。試しにプリプロセッサがどのように働くか見てみましょう。プリプロセッサコマンドはcppです。
cpp hello.cxx | more
いろいろなものが表示されました。主にtypedef
などの型宣言です。これにより、ストリーム入出力(iostream
)を行うために必要な定義が読み込まれるわけです。
ここでもう一つの情報がわかります。#include
というプリプロセッサ命令で/usr/include/c++/3.4.6/
というところにあるファイルが読み込まれていることがわかります。
ls /usr/include/c++/4.4.7
algorithm cstdarg functional sstream
array cstdatomic initializer_list stack
backward cstdbool iomanip stdatomic.h
bits cstddef ios stdexcept
bitset cstdint iosfwd streambuf
c++0x_warning.h cstdio iostream string
cassert cstdlib istream system_error
ccomplex cstring iterator tgmath.h
cctype ctgmath limits thread
cerrno ctime list tr1
cfenv cwchar locale tr1_impl
cfloat cwctype map tuple
chrono cxxabi-forced.h memory typeinfo
cinttypes cxxabi.h mutex type_traits
ciso646 debug new unordered_map
climits deque numeric unordered_set
clocale exception ostream utility
cmath exception_defines.h parallel valarray
complex exception_ptr.h queue vector
complex.h ext random x86_64-redhat-linux
condition_variable fenv.h ratio
csetjmp forward_list regex
csignal fstream set
なにやらいろいろありそうです。これらの勉強はまたそのうち。
次に
main() {
これは大域関数main
がここで定義されていることを示します。main
は特殊な関数で、エントリーポイントとなります。実行可能形式(a.out
)を作ったとき、そのプログラムのどこから実行を開始したらよいかを表します。C++の場合、main
関数に制御が渡されます。それ故、実行可能形式を作るときは必ず一つmain
関数を用意しなければなりません。
C++では関数は値を返す〜戻り値を持つ必要があります。古いC言語との互換性のために、「戻り値を明示しないときは整数型である」というルールがあります。この
main
関数はですから整数型の関数です。return
文で戻り値を明示していないためデフォルト値0
が返されます。
using namespace std;
この行の意味は、この先にmain
関数の中で出てくるシンボル・変数名などはstd
という名前空間にあるものと思えと言う宣言です。具体的にはcout
やendl
はiostream
というファイルで定義されているのですが、それらの定義はすべてstd
という名前空間の中で行われています。
C++プログラムの中に現れるものはいずれかの名前空間に属します。
教科書によっては
#include <iostream.h>
というように、後ろに.h
をつけたものが書かれているものもあります。<iostream.h>
と<iostream>
の違いは、前者が古い定義で匿名名前空間でクラスや型を定義しているのに対し、後者はstd
という名前空間内にそれらを定義しています。名前空間については後日詳細に説明します。
このusing namespace
を記述しない場合、次に述べるcout
やendl
がstd
という名前空間に属することを示すためにそれぞれ、std::cout
やstd::endl
という風に直接名前空間を指定する必要があります。
cout << "Hello, World!" << endl;
文法上はcout
というオブジェクトのオペレータ(関数の一種)<<
を、文字列"Hello, World!"
を引数として呼び出します。その結果、cout<<"Hello, World!"
という式が返すオブジェクトに対し、iostreamで定義されたendl
というオブジェクトを引数としてオペレータ<<
を呼び出します。(cout<<"Hello, World!")<<endl
意味がわかりますか?
効果としてはコンソール出力std::cout
に文字列"Hello, World!"
を出力(<<
)した後、改行(std::endl
)を出力すると考えてよいのですが。
プログラム開発をするときは自分が意図した概念が正しくソースコードに記述されているかどうか確認をすることが重要です。上に述べたような構文解読の習慣をつけましょう。
}
これで関数main
が閉じられます。
我々がC++を使うのはそれがオブジェクト指向技術と呼ばれるものに基づいて設計された言語であるからです。その基本的な構成要素であるオブジェクトはクラスというある種の型に基づいて生成されます。クラスを設計することがプログラム開発の上で非常に大きな比重を占めます。
ここはイントロですから、詳細は後回しにして、雰囲気をつかみましょう。MyFirstClass.cxxというファイルを作ります。
// MyFirstClass.cxx #include <iostream> class MyFirstClass { public : void printHello( ) { using namespace std; cout << "Hello, World!" << endl; } }; main( ) { MyFirstClass myObject; myObject.printHello( ); }
同様にコンパイル、実行をしてみましょう。
g++ MyFirstClass.cxx
./a.out
Hello, World!
実行結果は前の例と同じですが、ソースコードはずいぶん複雑になっています。
// MyFirstClass.cxx
まずこの行はコメント行です。C++では、//
はコメント導入を示し、行末までがコメントになります。
もう一つのコメントの表し方は/*
と*/
で囲むもので、これは複数行にわたっても有効です。
/*
*/
の中に/*
*/
の対を入れることは出来ません。/*
の後に再び/*
が来ても、それはコメントの一部と思われるため、無視。一方、最初に出現した*/
でコメントは終わりと取られます。その次から最後の*/
まではコメントではなくプログラムソースだと思われるため、たいがいエラーになります。時々やりますからご注意を。
#include <iostream>これは先ほどと同じ。コンソールへの書き出しをしたいので読み込みます。
class MyFirstClass { public : void printHello( ) { using namespace std; cout << "Hello, World!" << endl; } };
この部分でクラスMyFirstClass
を定義しています。パブリックなメソッド(メンバー関数)printHello
を持つだけのクラスで、このメソッドは先の例と同じHello,World!
をコンソールに出力するものであることがわかります。あくまでもここはクラスとそのメソッドの定義部分です。
main( ) { MyFirstClass myObject; myObject.printHello( ); }
ここがエントリーポイントであるmain
関数です。関数の中でクラスMyFirstClass
のオブジェクトmyObject
を定義します。オブジェクトとして作られることでクラスの機能は初めてコンピュータメモリー上に存在し、実行可能になります。myObject.printHello()
はmyObject
というオブジェクトのprintHello
というメソッドを呼び出しています。myObject
はMyFirstClass
クラスで作られたオブジェクトですからprintHello
というメソッドを持っています。
コンソールに表示がされるのはmain
関数が呼ばれ、myObject
が生成され、その次にprintHello
に制御がわたったときです。どのオブジェクトのどのメソッドが実行されているかを正しく追いかけることは非常に重要です。
この文書で使われる様々なものの名前の付け方やコーディングスタイルはATLAS C++ Conding Standard (ATL-SOFT-2002-001)に基づいています。出来るだけこの文書のスタイルに近づけることにより、ATLASのルールに従ったコーディングが出来るよう配慮しています。
次回はデータの扱い方について勉強しましょう。