TOP

C++入門

目次




はじめに

 

目次へ戻る

動作環境

 

目次へ戻る

対象者

 

目次へ戻る

 

C++とは?

 

目次へ戻る

環境構築

gcc3.3がインストールされていれば開発が出来ます。2.95の場合は、g++のフロントエンドが必要かもしれません。

 

目次へ戻る

最終目的

c++版の2cを作成するためC++の文法を理解します。C言語の開発時にヘッダファイルを確認する場合があるが、最近のLinuxやx86 Solaris9などでは、ヘッダファイルにC++の文法が含まれているため、そのレベルが解釈できるようにします。

 

目次へ戻る

コメント

// one line comment
/// one line comment
/* 
 * multiple comments
 */

 

目次へ戻る

コーディング規約

多くの規約がありそうです。

 

目次へ戻る

基本構造

文法はC言語の上位互換があるので、C言語系の言語を学んでいれば同様に利用できます。

 

目次へ戻る

ハローワールド

[s-okita@stoc cpp]$ cat hello.cpp
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
        cout << "Hello World!" << endl;
        return 0;
}

 

目次へ戻る

コンパイル

[s-okita@stoc cpp]$ g++ -o hello hello.cpp
[s-okita@stoc cpp]$ ./hello
Hello World!

coutとendlを宣言するために<iostream>を呼んでいます。<iostream.h>などの.hサフィックスがつかないので注意してください。またJavaのPackageと同様にモジュールをnamespaceで宣言しています。

[s-okita@stoc cpp]$ file /usr/include/c++/3.2/iostream
/usr/include/c++/3.2/iostream: C++ program text
 

namespaceの文をコメントアウトするgccではコンパイルできませんでした。以下がその時のログになります。

[s-okita@stoc cpp]$ g++ -o hello hello.cpp
hello.cpp: In function `int main(int, char**)':
hello.cpp:12: `cout' undeclared (first use this function)
hello.cpp:12: (Each undeclared identifier is reported only once for each
   function it appears in.)
hello.cpp:12: `endl' undeclared (first use this function)
[s-okita@stoc cpp]$ ls
hello.cpp  hello2.cpp
 

g++コンパイラは、ファイル名にhello.cppなどのほかに、.cc .cp .cxx .cpp .Cなども標準でC++言語としてコンパイルが可能です。またJavaのようにクラス名とファイル名を一致させる必要はありません。

 

目次へ戻る

データ形式

クラス以外の型は、基本的にC言語、Java言語での型と同じです。また真偽を判断するためにbool型が存在します。boolean型ではないので注意してください。1バイトを表現するbyte型は存在しません。

プリミティブ型(Primitive types)

Linuxではbool型をtypedefでint型を再定義しています。それを確認したとのでその時のログが以下になります。

[s-okita@stoc cpp]$ cat primitive_types.cpp
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
        char    cval = 'a';
        short   sval = 1;
        int     ival = 1;
        long    lval = 100;
        float   fval = 1.1;
        double  dval = 1.1;
        bool    flag = true;

        if ( flag == true )
        {
                cout << flag << endl;
        }

        bool test_bool = 1;
        if ( test_bool )
        {
                cout << "bool type maybe was defined typedef statement.." << endl;
        }

        return 0;
}
[s-okita@stoc cpp]$ g++ -o primitive_types primitive_types.cpp
[s-okita@stoc cpp]$ ./primitive_types
1
bool type maybe was defined typedef statement..
 

 

byte型はC++言語では存在しないのですが、確認してみます。

[s-okita@stoc cpp]$ cat primitive_types.cpp
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
        byte a = 0x00;
        return 0;
}
[s-okita@stoc cpp]$ g++ -o primitive_types primitive_types.cpp
primitive_types.cpp: In function `int main(int, char**)':
primitive_types.cpp:6: `byte' undeclared (first use this function)
primitive_types.cpp:6: (Each undeclared identifier is reported only once for
   each function it appears in.)
primitive_types.cpp:6: parse error before `=' token
 

定数(constants)

[s-okita@stoc cpp]$ cat constants.cpp
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
        const int MAX_SIZE = 1024;
        const char *P_CHAR_CONST = "HELLO";

        cout << MAX_SIZE << endl;
        cout << P_CHAR_CONST << endl;

        // compile error
        // MAX_SIZE = 200;

        // NO COMPILE ERROR!!!
        P_CHAR_CONST = "FUGA";
        cout << P_CHAR_CONST << endl;

        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o constants constants.cpp
[s-okita@stoc cpp]$ ./constants
1024
HELLO
FUGA
 

 

配列(Arrays)

  • C++の配列はJavaのようにlengthメソッドを持ちません。
  • インデックスのランタイムチェックがありません。
  • java.lang.System#arraycopyのようなコピー関数が存在しません。
  • 動的に配列のサイズが大きくなりません。
  • STLに上記を解決するVectorが存在します。これはJavaのArray型に影響を与えたことが予想されます。
    [s-okita@stoc cpp]$ cat arrays.cpp
    #include <iostream>
    using namespace std;
    
    void print_array(int ary [], int size)
    {
            for ( int i = 0; i < size; i++ )
            {
                    cout << ary[i] << endl;
            }
    }
    
    int main(int argc, char *argv[])
    {
            /* newを呼ばなくてもメモリ領域を確保する。 */
            int i_array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int i_multi_dimensional_arrays[10][20];
    
            print_array(i_array, 10);
    
            // 配列を以下のようは宣言できない。
            // int [10] i_array2;
    
            return 0;
    }
    [s-okita@stoc cpp]$ g++ -Wall -o arrays arrays.cpp
    arrays.cpp: In function `int main(int, char**)':
    arrays.cpp:16: warning: unused variable `int i_multi_dimensional_arrays[10][20]
       '
    [s-okita@stoc cpp]$ ./arrays
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
     



 

列挙型(Enumerations)

[s-okita@stoc cpp]$ cat enumerations.cpp
#include <iostream>
using namespace std;

enum Week { Sun, Mon, Tues, Wednes, Thurs, Sat };

int main(int argc, char *argv[])
{
        Week hoge;
        hoge = Sun;

        cout << hoge << endl;
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o enumerations enumerations.cpp
[s-okita@stoc cpp]$ ./enumerations
0
 

 

構造体(Structures)

[s-okita@stoc cpp]$ cat structure.cpp
#include <iostream>
using namespace std;

struct Status {
        char name [64];
        int  age;
        double weight;
};

int main(int argc, char *argv[])
{
        Status myStat;
        strncpy(myStat.name, "satoshi okita", sizeof(myStat.name));
        myStat.age = 26;
        myStat.weight = 55.0;

        cout << myStat.name << endl;
        cout << myStat.age  << endl;
        cout << myStat.weight << endl;
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o structure structure.cpp
[s-okita@stoc cpp]$ ./structure
satoshi okita
26
55
 

 

共用体(Union)

 

ポインタ(Pointers)

[s-okita@stoc cpp]$ cat pointer.cpp
#include <iostream>
#include <stdio.h>
using namespace std;

int main(int argc, char *argv[])
{
        /*
         * p is pointer variable.
         * x is valiable NO POINTER!!!
         */
        int *px, x;

        x = 100;
        px = &x;

        cout << *px << endl;
        cout << px << endl;

        px = NULL;

        cout << px << endl;
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o pointer pointer.cpp
[s-okita@stoc cpp]$ ./pointer
100
0xbfffe700
0
 

newによるヒープ領域へのメモリ割り当て確認。C言語の場合、そのサイズ文mallocを使用しました。C言語とC++言語を混在しない場合は、基本的にnewキーワードでメモリ管理を行うべきだと思います。

[s-okita@stoc cpp]$ cat pointer_new.cpp
#include <iostream>
#include <stdio.h>

using namespace std;

int main(int argc, char argv[])
{
        int *p;
        p = new int;

        *p = 200;

        cout << *p << endl;
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o pointer_new pointer_new.cpp
[s-okita@stoc cpp]$ ./pointer_new
200
 

メモリアドレスの比較とメモリデータの比較

[s-okita@stoc cpp]$ cat pointer_expression.cpp
#include <iostream>
#include <stdio.h>

using namespace std;

int main(int argc, char *argv[])
{
        int *px;
        int *py;

        px = new int;
        py = new int;

        *px = 100;
        *py = 100;

        /* print address */
        cout << "px addres=" << px << endl;
        cout << "py addres=" << py << endl;

        /* the pointer expression does NOT compare values */
        if ( px != py )
        {
                cout << "ADDRESS COMPARE" << endl;
        }

        if ( *px == *py)
        {
                cout << "VALUE COMPARE:" << *px << endl;
        }

        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o pointer_expression pointer_expression.cpp
[s-okita@stoc cpp]$ ./pointer_expression
px addres=0x8049be0
py addres=0x8049bf0
ADDRESS COMPARE
VALUE COMPARE:100
 

メモリの割り当てにnew/deleteキーワードを使います。Java言語と異なりプリミティブ型にもnew/deleteを利用してヒープ領域へのメモリ割り当て/開放を行います。

[s-okita@stoc cpp]$ cat pointer_heap.cpp
#include <stdio.h>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
        /*
         * c++言語はヒープ領域を割り当てはnew/deleteキーワードでおこなう。
         */
        int *p;
        p = new int;
        *p = 100;
        cout << *p << endl;
        delete p;

        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o pointer_heap pointer_heap.cpp
[s-okita@stoc cpp]$ ./pointer_heap
100
 

WARNING memory leak!!

[s-okita@stoc cpp]$ cat pointer_leak.cpp
#include <stdio.h>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
        int *p;

        p = new int;

        *p = 100;

        p = NULL;

        /* NULLを代入しただけで最初にnewでメモリを割り当てられた部分は開放していない*/
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o pointer_leak  pointer_leak.cpp
[s-okita@stoc cpp]$ ./pointer_leak
 

配列型もnewキーワードでメモリを確保できるので実行してみます。

[s-okita@stoc cpp]$ cat ./array_new.cpp
#include <stdio.h>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
        int *array;

        array = new int [10];

        for ( int i = 0; i < 10; i++ )
        {
                *(array + i) = i;
        }

        for ( int i = 0; i < 10; i++ )
        {
                cout << *(array + i) << endl;
        }

        delete [] array;

        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o array_new array_new.cpp
[s-okita@stoc cpp]$ ./array_new
0
1
2
3
4
5
6
7
8
9
 

 

目次へ戻る

演算子

C言語と同様です。

[s-okita@stoc cpp]$ cat chained.cpp
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
        int one = 1;
        int two = 2;
        int three = 3;


        /* プリミティブ型を文字として解釈して表示する。*/
        cout << one << two << three ;

        return 0;
}
[s-okita@stoc cpp]$ g++ -o chained chained.cpp
[s-okita@stoc cpp]$ ./chained
123[s-okita@stoc cpp]$

 

目次へ戻る

I/O

 

[s-okita@stoc c++]$ cat io.cpp
#include <stdio.h>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
        int x, y;
        cin >> x;
        cin >> y;

        cout << "x=" << x << endl;
        cerr << "y=" << y << endl;
}
[s-okita@stoc c++]$ g++ -Wall -o io io.cpp
[s-okita@stoc c++]$ ./io
1
2
x=1
y=2
 

 

[s-okita@stoc c++]$ cat file_io.cpp
#include <stdio.h>
#include <iostream>
#include <fstream>

using namespace std;

void close_function(ifstream & v_ifs)
{
        v_ifs.close();
        if ( v_ifs.fail() == true )
        {
                cerr << "close error" << endl;
        }
        else
        {
                cerr << "close success" << endl;
        }
}
int main(int argc, char *argv[])
{
        ifstream ifs;
        ifs.open("test.dat");
        if ( ifs.fail() == true )
        {
                cerr << "unable to open" << endl;
        }
        else
        {
                cout << "open" << endl;
        }

        int tmp;
        while ( ifs >> tmp )
        {
                cout << "tmp=" << tmp << endl;
        }

        close_function(ifs);

        return 0;
}
[s-okita@stoc c++]$ g++ -Wall -o file_io file_io.cpp
[s-okita@stoc c++]$ ./file_io
unable to open
close error
 

 

目次へ戻る

制御構造

分岐

[s-okita@stoc c++]$ cat condition.cpp
#include <iostream>
#include <stdio.h>

using namespace std;

int main(int argc, char *argv[])
{
        bool aaa = false;

        if ( aaa )
        {
                cout << "aaa is true" << endl;
        }

        if ( aaa == false )
        {
                cout << "aaa is false" << endl;
        }
        return 0;
}
[s-okita@stoc c++]$ g++ -Wall -o condition condition.cpp
[s-okita@stoc c++]$ ./condition
aaa is false
 

 

反復

[s-okita@stoc cpp]$ cat loop.cpp
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
        /* Java言語と同様に必要な場所で宣言が可能 */
        for ( int i = 0; i < 10; i++ )
        {
                cout << i << endl;
        }

        int j = 0;
        while ( j++ < 10 )
        {
                cout << j << endl;
        }
        return 0;


}
[s-okita@stoc cpp]$ g++ -Wall -o loop loop.cpp
[s-okita@stoc cpp]$ ./loop
0
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
10
 

 

目次へ戻る

関数

[s-okita@stoc cpp]$ cat function.cpp
#include <iostream>
using namespace std;

/* forward declaretion
 * C言語のプロトタイプ宣言
 */

int print_hello();

int main(int argc, char *argv[])
{
        int return_code;
        return_code = print_hello();
        if ( return_code == 1 )
        {
                cout << "SUCCESS" << endl;
        }
        else
        {
                cerr << "ERROR" << endl;
        }
        return 0;
}

int print_hello()
{
        cout << "Hello" << endl;
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o function  function.cpp
[s-okita@stoc cpp]$ ./function
Hello
ERROR
[s-okita@stoc cpp]$ ./function 1> /dev/null
ERROR
 

リファレンスとポインタ

アンパサンドを利用することでリファレンスという機能が使える。Java言語と同様。
[s-okita@stoc c++]$ cat passing_mode.cpp
#include <stdio.h>
#include <iostream>

using namespace std;

void passing_mode_by_value( int val )
{
        val = 200;
        cout << val << " in passing_mode_by_value." << endl;
}

void passing_mode_by_reference( int & ref )
{
        ref = 500;
        cout << ref << " in passing_mode_by_reference." << endl;

}

void passing_mode_by_pointer( int *p)
{
        *p = 700;
        cout << *p << " in passing_mode_by_pointer." << endl;
}

int main(int argc, char *argv[])
{
        int x, y;
        int *p_x;
        int *p_y;

        p_x = &x;
        p_y = &y;

        *p_x = 111;
        *p_y = 999;

        cout << "x=" << x << endl;
        passing_mode_by_value( x );
        cout << "x=" << x << endl;
        passing_mode_by_reference( x );
        cout << "x=" << x << endl;
        passing_mode_by_pointer( p_x );
        cout << "x=" << *p_x << endl;

        return 0;
}
[s-okita@stoc c++]$ g++ -Wall -o passing_mode passing_mode.cpp
[s-okita@stoc c++]$ ./passing_mode
x=111
200 in passing_mode_by_value.
x=111
500 in passing_mode_by_reference.
x=500
700 in passing_mode_by_pointer.
x=700
 

 

目次へ戻る

ライブラリ STL (C++ Standard Template Library)

stringクラスを試してみる。

[s-okita@stoc cpp]$ cat stringTest.cpp
#include <iostream>
#include <string>

using namespace std;
int main(int argc, char *argv[])
{
        string s1 = "HELLO";
        string s2("HELLO");

        cout << s1.size() << endl;
        cout << s1.length() << endl;

        if ( s1 == s2 )
                cout << " true " << endl;

        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o stringTest stringTest.cpp
[s-okita@stoc cpp]$ ./stringTest
5
5
 true
 

Vectorクラスを試してみる

[s-okita@stoc cpp]$ cat vectorTest.cpp
#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char *argv[])
{
        vector<int> v;

        cout << "size:" << v.size() << endl;

        v.push_back(3);
        v.push_back(5);

        cout << "size:" << v.size() << endl;

        for ( unsigned int i = 0; i < v.size(); i++ )
        {
                cout << v[i] << endl;
        }
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o vectorTest vectorTest.cpp
[s-okita@stoc cpp]$ ./vectorTest
size:0
size:2
3
5
 

 

目次へ戻る

クラス




[s-okita@stoc cpp]$ cat class_ini.cpp
#include <iostream>

using namespace std;

/*
 * クラスの宣言
 *
 * セミコロンが最後に必要なので注意することが必要です。また、コンストラクタで
 * 初期化処理をおこない、デストラクタで後処理を行う。
 */
class class_ini {
        int aaa;
        public:
                class_ini();            /* コンストラクタ       */
                ~class_ini();           /* デストラクタ         */
                void show();            /* メンバー関数         */
};

class_ini::class_ini() {
        cout << "invoked constructer" << endl;
}

class_ini::~class_ini() {
        cout << "invoked destructer" << endl;
}

void class_ini::show() {
        cout << " test show " << endl;
}

int main(int argc, char *argv[])
{
        /* メモリの割り当て */
        class_ini* obj = new class_ini();

        /* 処理を実行 */
        obj->show();

        /* メモリの開放 */
        delete obj;
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o class_ini class_ini.cpp
[s-okita@stoc cpp]$ ./class_ini
invoked constructer
 test show
invoked destructer

 

コンストラクタに引数をつけてみる

[s-okita@stoc cpp]$ cat constructor2.cpp
#include <iostream>
#include <string>

using namespace std;

class Person {

        string  name;
        int             age;
        public:
                Person();
                Person(string vname, int vage);
                ~Person();
                void show();
};

Person::Person()
{
}

Person::Person(string vname, int vage)
{
        name = vname;
        age  = vage;
}

Person::~Person()
{
        cout << "destructor" << endl;
}

void Person::show()
{
        cout << name << endl;
        cout << age  << endl;
}

int main(int argc, char *argv[])
{

        Person *pObj = new Person("Satoshi", 26);
        pObj->show();
        delete pObj;
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o constructor2 constructor2.cpp
[s-okita@stoc cpp]$ ./constructor2
Satoshi
26
destructor

 

目次へ戻る

継承(Inheritance)

 

[s-okita@stoc cpp]$ cat inheritance.cpp
#include <iostream>

using namespace std;

/* 継承の元となるクラスを基本クラス(Base Class)と呼ぶ */
class BaseClass {
        double height;
        double weight;
        public:
        BaseClass();
        void show();
};

BaseClass::BaseClass()
{
        cout << "load constructor" << endl;
        height = 1.1;
        weight = 2.2;
}

void BaseClass::show()
{
        cout << height << endl;
        cout << weight << endl;
}

/* 派生クラスと呼ぶ(DerivedClass)
 * publicにBaseClassクラスを継承する。
 */
class DerivedClass : public BaseClass {
        char blood;
        public:
        DerivedClass();
        void showBlood();
};

DerivedClass::DerivedClass() {
        cout << "load constructor" << endl;
        blood = 'B';
}

void DerivedClass::showBlood()
{
        cout << blood << endl;
}

int main(int argc, char *argv[])
{
        DerivedClass *pDC = new DerivedClass();
        pDC->show();
        pDC->showBlood();
        delete pDC;

        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o inheritance inheritance.cpp
[s-okita@stoc cpp]$ ./inheritance
load constructor
load constructor
1.1
2.2
B
 

 

目次へ戻る

ポリモーフィズム(Polymorphism)

 

目次へ戻る

Virtual Function (仮想関数)



 

[s-okita@stoc cpp]$ cat DynamicOverride.cpp
/*
 * Dynamic Override.cpp
 * ポリモーフィズムを実現する機能。仮想関数(Virtual Function)と呼ぶ
 */
#include <iostream>

using namespace std;

class DynaBase
{
public:
  virtual void printHello ()
  {
    cout << "hello" << endl;
  }

  void show ()
  {
    cout << "fuga" << endl;
  }
};

class GoodbyeClass:public DynaBase
{
  public:void printHello ()
  {
    cout << "goodbye" << endl;
  }

  void show ()
  {
    cout << "hoge" << endl;
  }
};

int
main (int argc, char *argv[])
{
  DynaBase daObj;
  GoodbyeClass gcObj;

  DynaBase *pDynaBase;
  pDynaBase = &daObj;

  /* 実行時にオブジェクトを確認してそのメンバ関数を呼び出す */
  pDynaBase->printHello ();
  /* コンパイル時にベースクラスのメンバ関数に確定される */
  pDynaBase->show ();

  pDynaBase = &gcObj;

  /* 実行時にオブジェクトを確認してそのメンバ関数を呼び出す */
  pDynaBase->printHello ();
  /* コンパイル時にベースクラスのメンバ関数に確定される */
  pDynaBase->show ();

  return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o DynamicOverride DynamicOverride.cpp
[s-okita@stoc cpp]$ ./DynamicOverride
hello
fuga
goodbye
fuga
 

 

目次へ戻る

抽象クラス

[s-okita@stoc cpp]$ cat AbstructClass.cpp
/* JavaでのAbstructクラスまたはInterfaceを実現するためには
 * C++では仮想関数を利用する。
 */
#include <iostream>
#include <string>

using namespace std;

/*
 * 抽象クラスになる例
 */
class AbstructClass {
        public:
                /* 抽象化するためにabstructキーワードは存在しない
                 * それを実現するために関数の宣言時に=0を指定する。
                 */
                virtual void show(string name) = 0;
};

/*
 * 抽象クラスを継承する場合は、必ずベースクラスの関数を実装しなければならない
 */
class ComclateClass : public AbstructClass {
        public:
                void show(string name)
                {
                        cout << name << endl;
                }
};

int main(int argc, char *argv[])
{
        AbstructClass *pAC = new ComclateClass;
        pAC->show("polymorphism");
        delete pAC;
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o AbstructClass AbstructClass.cpp
[s-okita@stoc cpp]$ ./AbstructClass
polymorphism
 

 

目次へ戻る

インライン関数

インライン関数は、C言語のマクロ定義の代用に出来る。関数呼び出しのオーバーヘッドがないためである。
Java言語ではメソッドにfinal修飾子をつけることでインライン化が可能である。パフォーマンスを求める時に
利用できる。Javaのようにクラス定義内に関数を書くとinline関数となる。
[s-okita@stoc cpp]$ cat inline.cpp
#include <iostream>

using namespace std;

/* インライン関数
 * * C++言語では、一般にマクロ定義をインライン関数でおこなう。
 * */
inline int func(int x)
{
        return x * 100;
}

class TestClass {
        int status;

        public:
        TestClass();
        ~TestClass();
        void show();

        /* インラインメンバ関数
         * * Javaでいうfinalキーワードを実装しているのと同様
         * */
        void showInline()
        {
                cout << "write as java code, inline member function!" << endl;
        }

        /* インラインキーワードを使ってインラインメンバ関数を
         * * 記述する例
         * */
        inline void showInline2()
        {
                cout << "write inline keyword." << endl;
        }
};

TestClass::TestClass()
{
        cout << "load constructor" << endl;
        status = 100;
}

TestClass::~TestClass()
{
        cout << "load destructor" << endl;
}

void TestClass::show()
{
        cout << status << endl;
        cout << func(100) << endl;
}


int main(int argc, char *argv[])
{
        TestClass *pObj;
        pObj = new TestClass();
        pObj->show();
        pObj->showInline();
        pObj->showInline2();
        delete pObj;
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o inline inline.cpp
[s-okita@stoc cpp]$ ./inline
load constructor
100
10000
write as java code, inline member function!
write inline keyword.
load destructor
 

 

目次へ戻る

スタティックメンバ変数・スタティックメンバ関数

[s-okita@stoc cpp]$ cat static.cpp
#include <iostream>
#include <string>

using namespace std;


class StaticTestClass {
        string username;
        public:
        StaticTestClass();
        StaticTestClass(string name);
        static string company_name; /* スタティックメンバ変数の定義*/

        void showPrivateData();
        static long getUniqueSerialNumber();
};

/* スタティックメンバ変数は、クラス定義の後で再宣言しないと使えない */
string StaticTestClass::company_name = "R&D, inc";

StaticTestClass::StaticTestClass()
{
        username = "";
}

StaticTestClass::StaticTestClass(string username)
{
        /* Java言語と同様thisキーワードが使える
         * * 自分のオブジェクトを参照できる
         * * ただ、ポインタと同様なため->アロー演算子を利用する事
         * */
        this->username = username;
}

void StaticTestClass::showPrivateData()
{
        cout << username << endl;
}

long StaticTestClass::getUniqueSerialNumber()
{
        /* 本来は乱数などでシリアルを生成する */
        return 100 * 20;
}

int main(int argc, char *argv[])
{
        StaticTestClass *pObj = new StaticTestClass("satoshi");
        pObj->showPrivateData();
        cout << StaticTestClass::company_name << endl;

        cout << StaticTestClass::getUniqueSerialNumber() << endl;
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o static static.cpp
[s-okita@stoc cpp]$ ./static
satoshi
R&D, inc
2000
 

 

目次へ戻る

リファレンス

C++では、データを渡す際にリファレンスという機能がある。ポインタとは異なる。

[s-okita@stoc cpp]$ cat references.cpp
/* references.cpp
 *
 * リファレンスは、変数の別名Aliasとして使われる
 * 宣言には&をつかう。
 */
#include <iostream>

using namespace std;

class TestClass {
        public:
                TestClass(string name);
                string name;
};

TestClass::TestClass(string name)
{
        this->name = name;
}

int main(int argc, char *argv[])
{
        /* 実体の作成 */
        TestClass ts("satoshi");

        /* リファレンスの作成 */
        TestClass &ref = ts;

        cout << ref.name << endl;

        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o references references.cpp
[s-okita@stoc cpp]$ ./references
satoshi
 

 

値渡しのサンプル

[s-okita@stoc cpp]$ cat ByValue.cpp
#include <iostream>
#include <string>

using namespace std;

class TestClass
{
  string name;
public:
    TestClass ();
  void setName (string name);
  string getName ();
};

TestClass::TestClass ()
{
  this->name = "default";
  cout << "constructor data set: " << name << endl;
}

void
TestClass::setName (string name)
{
  this->name = name;
}

string
TestClass::getName ()
{
  return this->name;
}

void
testByValue (TestClass ts)
{
  /* 値渡しのためデータは反映されない */
  ts.setName ("aaa");
}

int
main (int argc, char *argv[])
{
  TestClass ts;
  testByValue (ts);
  cout << ts.getName () << endl;
  return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o ByValue ByValue.cpp
[s-okita@stoc cpp]$ ./ByValue
constructor data set: default
default
 

 

参照渡しのサンプル(C++機能のリファレンスを使う)

[s-okita@stoc cpp]$ cat ByReferences.cpp
/* C/C++言語では、呼び出し元のデータを変更するためにはアドレスの参照渡し
 * する必要がある。C++では、ポインタを使わずにアドレスを渡せる
 * これは、サンプルを見てもらえば分かるが関数を使う側はアドレスを渡すか、実体を
 * 渡すか意識しなくて良い。Java言語のリファレンス機能と同様。
 * Javaはこれをさらに発展させて&記号を使っていない。
 */

#include <iostream>
#include <string>

using namespace std;

class RefClass
{
  string name;
public:
    RefClass (string name);
  void show ();
};

RefClass::RefClass (string name)
{
  this->name = name;
  cout << "constructor" << endl;
}

void
RefClass::show ()
{
  cout << name << endl;
}

void
testRefFunction (RefClass & ref)
{
  ref.show ();
}

int
main (int argc, char *argv[])
{
  RefClass rc ("satoshi");

  testRefFunction (rc);

  return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o ByReferences ByReferences.cpp
[s-okita@stoc cpp]$ ./ByReferences
constructor
satoshi
 

 

目次へ戻る

フレンド関数

privateなメンバ変数にアクセスするには、通常そのクラスにpublicなメンバ関数を作る。これはJavaやRubyなど多くのオブジェクト言語では同様の機能を持っている。C++には、この方法以外にもフレンドという機能がある。

[s-okita@stoc cpp]$ cat friend.cpp
/* friend.cpp */

#include <iostream>
#include <string>

using namespace std;

class TestClass {
        string name;
        friend void showPrivateData(TestClass &ref);
        public:
        TestClass(string name);
};

TestClass::TestClass(string name)
{
        this->name = name;
}

void showPrivateData(TestClass &ref)
{
        cout << ref.name << endl;
}

int main(int argc, char *argv[])
{
        TestClass ts("okita");
        TestClass &ref = ts;
        showPrivateData(ref);
        return 0;
}

[s-okita@stoc cpp]$ g++ -Wall -O2 -o friend friend.cpp
[s-okita@stoc cpp]$ ./friend
okita
 

 

目次へ戻る

オーバーロード(Overload)

[s-okita@stoc cpp]$ cat overload.cpp
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
        int i = 0;
        double trouble = 99.9;
        char a_character = 'a';
        char b_character = 'b';

        /*
         * cout << プリミティブ型 << endl;
         * C言語と異なり、どのようなプリミティブ型でも同じ書き方で表示できる
         */
        cout << i << endl;
        cout << trouble << endl;
        cout << a_character << endl;
        cout << b_character << endl;

        return 0;
}
[s-okita@stoc cpp]$ g++ -o overload overload.cpp
[s-okita@stoc cpp]$ ./overload
0
99.9
a
b
 
目次へ戻る

例外処理




Java言語と同様、throw, try, catchキーワードで実装する。

[s-okita@stoc cpp]$ cat Exception.cpp
/* 初期のC++では、例外処理を実装していなかったが
 * 現在のC++では、例外処理を実装できる。C言語などでは、通常の処理を
 * コーディングしている途中にエラー時の処理を記述していた傾向があるため
 * 可視性が悪かった。それを防ぐ機能。
 * 基本的にJavaの例外処理を同様である。
 */

#include <iostream>
#include <string>

using namespace std;

char *errorMessage = "Exception : isNotZero";

class ExceptionSample
{
  public:int isZero (int i) throw (char *);
};

/* ゼロであれば、100を返すサンプル関数
 * エラー処理をExceptionで実装しているため戻り値をエラー用に使わなくてすむ
 */
int
ExceptionSample::isZero (int i)
throw (char *)
{
  cout << "isZero start" << endl;
  if (i != 0)
    {
      throw errorMessage;
    }
  return 100;
}

int
main (int argc, char *argv[])
{
  ExceptionSample *es = new ExceptionSample;
  int testData = 100;
  try
  {
    es->isZero (testData);
  }
  catch (char *errorMessage)
  {
    cout << "char *" << endl;
    cout << errorMessage << endl;
  }
  catch (...)
  {
    cout << "..." << endl;
    cout << "finally keyword in Java." << endl;
  }
  delete es;
  return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o Exception Exception.cpp
[s-okita@stoc cpp]$ ./Exception
isZero start
char *
Exception : isNotZero
 

 

目次へ戻る

ネームスペース(名前空間)




[s-okita@stoc cpp]$ cat namespace.cpp
/* Java言語のpackageに相当する機能をnamespaceで実現する */

#include <iostream>
#include <string>

/* coutを利用するためにstdを宣言 */
using namespace std;

namespace print_pkg
{
  string print ()
  {
    return "hoge";
  }
}

/* print_pkgの利用を宣言する。これによりprint関数が使える */
using namespace print_pkg;

int
main (int argc, char *argv[])
{
  /* using namespace print_pkg;が存在しないとエラー */
  cout << print () << endl;

  cout << print_pkg::print () << endl;

  /* using namespace std;が宣言していない場合は、以下のように
   * ネームスペース::オブジェクトのように利用しなければならない。
   */
  std::cout << "test" << endl;

  return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o namespace namespace.cpp
[s-okita@stoc cpp]$ ./namespace
hoge
hoge
test
 
目次へ戻る

テンプレート




ポリモーフィズムを実現する機能の1つです。テンプレートはライブラリを作成する際に非常に重宝します。JavaでもJDK5.0からgenericsという名称でテンプレート機能が実装されました。

[s-okita@stoc cpp]$ cat template_function.cpp
#include <iostream>
#include <string>

/* テンプレート機能は、オーバーロードの代用として利用できる。
 * また、テンプレートは、コンパイル時にコンパイラが、
 * その型に合ったインスタンスを
 * 生成するという特徴がある。
 */
using namespace std;

template < class T > T add (T & l, T & r)
{
  return l + r;
}

int
main (int argc, char *argv[])
{
  int i = 100;
  int j = 200;
  cout << add (i, j) << endl;

  string first = "satoshi";
  string last = "okita";

  cout << add (first, last) << endl;
  return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o template_function template_function.cpp
[s-okita@stoc cpp]$ ./template_function
300
satoshiokita

 

[s-okita@stoc cpp]$ cat template_class.cpp
#include <iostream>
#include <string>

using namespace std;

/* クラステンプレート */
template < class T > class XX
{
public:
  T square (T t)
  {
    return t * t;
  }
};

/* 引数のあるクラステンプレート */
template < class T, int n > class X
{
public:
  T add ()
  {
    return n * 100;
  }
};

int
main (int argc, char *argv[])
{
  XX < int >variable1;
  int i = 100;
  cout << variable1.square (i) << endl;

  X < float, 22 > x1;
  cout << x1.add () << endl;
  return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -O2 -o template_class template_class.cpp
[s-okita@stoc cpp]$ ./template_class
10000
2200

 

目次へ戻る

C言語のリンケージ

C言語で記述したオブジェクトファイルをC++言語に結合するにはexternキーワードを利用する

[s-okita@stoc cpp]$ cat clink.c
#include <stdio.h>

void hello()
{
        printf("hello\n");
}
[s-okita@stoc cpp]$ gcc -Wall -O2 -c clink.c
[s-okita@stoc cpp]$ cat cpplink.cpp
#include <iostream>

/* C言語で作られている事をexternキーワードで指定する */
extern "C" {
        void hello();
}

int main(int argc, char *argv[])
{
        hello();
        return 0;
}
[s-okita@stoc cpp]$ g++ -Wall -o cpplink cpplink.cpp  clink.o
[s-okita@stoc cpp]$ ./cpplink
hello
 

 

目次へ戻る

デバック

 

 

目次へ戻る

最後に

 

 

目次へ戻る

参考資料

Learning a New Programming Language: C++ for Java Programmers(英語)

目次へ戻る


イバラキングへのリンク Get Firefox Valid XHTML 1.1 Apple Darwinへのリンク