第1章
2つのバージョンがある。 新しいバージョン
#include <iostream>
using namespace std;
↓ 古いバージョン
#include <iostream.h>
第2章
継承
class Base {
…
public:
…
};
class Derived : public Base {
…
public:
…
};
構造体はデフォルトでメンバが公開であるクラス。
共用体はデフォルトでメンバが公開であり、さらに制限があるクラス。 他のクラスを継承できない。staticメンバをもてない。 コンストラクタ、デストラクタを持つオブジェクトをもてない。 仮想メンバ関数をもてない。
無名共用体はコンパイラに変数が同じアドレスにあることを伝えることができる。直接アクセスが可能。 非公開メンバを含めることはできない。 メンバが同じスコープ内のほかの識別子と重複してはいけない。 グローバル無名共用体はstaticとして宣言しなければならない。
union {
int i;
char ch[4];
}
i = 10;
ch[0] = 'x';
インライン関数は使用するより前に定義しなければいけない。
第3章
オブジェクトの代入はメンバがビット単位で代入される。 メンバが動的割り当ての場合は注意が必要。
関数にオブジェクトを引数とした場合はコピーが作成される。 このときコンストラクタは実行されない。 関数終了時にオブジェクトが破棄され、デストラクタが実行される。 コンパイラによっては関数を呼ぶ側と呼ばれる側で2重にオブジェクトを複製するので注意。
オブジェクトを関数の戻り値とした場合は戻った時に一時オブジェクトが作成される。 そのためデストラクタは2回実行される。
フレンド関数はクラスの非公開メンバにアクセスが可能。 フレンド関数を使用するときは宣言をクラス内に書き、定義は通常の関数として書く。 フレンド関数は継承されない。
class Class {
int a;
public:
friend int FriendFunc(Class ob);
};
int FriendFunc(Class ob)
{
ob.a = 0;
}
int main()
{
Class ob;
FriendFunc(ob);
}
第4章
newが失敗を示す方法は2通りありヌルを返すか、例外を生成するか。
newの割り当て時に初期値を与える
p-var = new type(initial-value);
newで配列を割り当てる。初期化はできない。
p-var = new type[size];
delete [] p-var;
配列の各要素ごとにコンストラクタ・デストラクタを実行
参照変数は宣言時にじゃなく&を使用。渡す時に&は不要。使用時には不要。 参照が差すものを変更できない。 オブジェクトを参照で使用するときは->でなく.を使用。
参照返しは参照を返すため式の左辺に使用可能。ただしスコープに注意。
独立参照は宣言時に初期化が必要。
第5章
引数を受け取るコンストラクタを作成した場合、引数を受け取らないコンストラクタも作成すべき。
コピーコンストラクタは仮引数を次のようにして宣言する。obはコピーされるオブジェクト。
class-name(const class-name &ob);
コピーコンストラクタは代入の時には使用されない。宣言文、仮引数、戻値のとき使用される。
デフォルト引数は定数かグローバル変数でなければいけない。
オーバーロード関数のアドレスの探し方は関数ポインタの宣言時にオーバーロード関数の宣言と比較される。
第6章
演算子のオーバーロード
return-type class::operator#(arg-list)
.、::、.*、?はオーバーロードできない。プリプロセッサ演算子もできない。
2項演算子のオーバーロード
class coord {
int x, y;
public:
coord operator+(coord ob-right);
}
coord coord::operator+(class-name ob-right)
{
}
仮引数は左辺のオブジェクトで、右辺のオブジェクトはthisポインタでよってわたされる。
単項演算子のオーバーロードは仮引数をとらない。 後値の宣言には仮引数(int notused)をつける。
フレンド演算子関数にはできないものがある。代入演算子、[]演算子とか。 thisポインタがないため右辺も明示して渡す必要がある。
第7章
public継承は基本クラスの非公開はそのまま、公開は派生クラスの公開、被保護は派生クラスの被保護になる。
private継承は基本クラスの非公開はそのまま、公開は派生クラスの非公開、被保護は派生クラスの非公開になる。
protected継承は基本クラスの非公開はそのまま、公開は派生の被保護、非保護は派生の被保護になる。
コンストラクタは派生順に実行され、デストラクタは逆の順で実行される。
基本クラスのコンストラクタに引数を渡す時は
derived(arg-list) : base(arg-list) {
}
とする。 例えば
derived(int n, int m) : base(m) {
}
多重継承
class derived : access base1, access 2, ... {
}
コンストラクタは指定順に、デストラクタは逆に実行される。
仮想基本クラスは多重継承で同じ基本クラスを2つ以上継承するのを防ぐ時にしよう。
class derived : virtual access basae {
}
第8章
«オーバーロード(挿入関数)
ostream &operator <<(ostream &stream, class-name ob)
{
return stream;
}
メンバ関数にはできないので通常はフレンド関数として実装される。
オーバーロード(抽出関数)
istream &operator >>(istream &stream, class-name ob)
{
return stream;
}
第9章
仮引数をとらない入/出力マニピュレータ
istream &manip-name(istream &stream)
{
return stream;
}
ostream &manip-name(ostream &stream)
{
return stream;
}
第10章
基本クラスのポインタは派生クラスもさせる。ただしアクセスできるのは基本クラスのメンバのみ。
仮想関数を使用すると派生クラスで実装したメンバにもアクセスできる。
仮想関数を派生クラスで実装しない場合は基本クラスの関数が呼ばれる。
強制的に派生クラスで仮想関数を実装させる方法(純粋仮想関数)
virtual type func-name(arg-list) = 0;
純粋仮想関数を含んでいるクラスを抽象クラスと呼ぶ。
第11章
テンプレート関数
template <class Ttype1, class Ttype2, ...> ret-type func-name(arg-list)
{
}
もしくは
template <typename Ttype1, typename Ttype2, ...> ret-type func-name(arg-list)
{
}
テンプレート関数を明示的にオーバーロードすると自動で生成されなくなり、明示した関数が呼ばれる。 この場合一般的にはテンプレートでなくオーバーロードで実装する。
テンプレートクラス
tenplate <class Ttype> class class-name {
};
class-name <type> ob;
例外処理
try {
throw exception;
}
catch (type1 arg) {
}
catch (type2 arg) {
}
:
argは使用しないときは省略できる。 catchで指定していない型をthrowするとterminate()が呼ばれる、通常はabort()で停止する。
すべての例外をキャッチする
catch (...) {
}
関数が呼び出し元に投げる例外の方を制限する。
ret-type func-name(arg-list) throw(type-list)
}
}
許可されていない例外を投げるとunexpected()が呼ばれる、通常はterminate()が呼ばれる。
例外ハンドラの内部からさらに外側のtry/catchブロックに例外を投げるにはthorwのみ(例外を指定しない)を書く。
new演算子の例外処理 <new> をインクルードする必要がある。 newが失敗した時はbad_alloc例外を投げる。古いのではxallocを投げる。 失敗時に例外を投げずにNULLを返す方法
p = new(nothrow) type;
第12章
実行時型情報(RTTI) <typeinfo> をインクルードする必要あり。
typeid(ob)
でtype_info型のオブジェクトへの参照を得る。 type_infoクラスのメンバ関数には
bool operator==(const type_info &ob); //型が一致するか
bool operator!=(const type_info &ob); //型が不一致か
bool before(const type_info &ob); //照合順序が指定したオブジェクトより前にあるか
cosnt char *name(); //方の名前を指すポインタを返す
typeid(type-name)
で指定の型のtype_infoオブジェクトを取得可能。比較で使用可能。
typeidをテンプレートクラスに適用
template <class T> class Num {
};
if (typeid(ob).name() == typeid(Num<int>))
dynamic_cast<target-type> (expr)
target-typeとexprはポインタか参照型でなければいけない。 ポインタの型変換に失敗すると評価結果がNULLになる。 参照の型変換に失敗するとbad_cast例外が投げられる。
他のキャスト演算子
const_castはconstやvolatileの指定を上書きできる。変換先の型はconstやvolatileの違いを除いて元の型と同じでなければいけない。
static_castは非ポリモーフィック型変換を行う。実行時の検査は行われない。
reinterpret_castはある型を基本的に異なる別の型に変更できる。
第13章
名前空間の宣言
namespace name {
}
同じ名前の名前空間宣言を複数記述することもできる。
名前空間の外部からのアクセスには名前空間の名前とスコープ解決演算子をつける。
using namespace name;
using name::member;
でそれを省略可能。
無名名前空間は1つのファイル内でのみ認識される識別子を定義することができる。 ファイル外では識別子を認識することができない。
namespace {
}
変換関数は変換を行うクラスのメンバでなければいけない。
operator int() {return value;}
オブジェクトを自動的に変換してくれる。
staticクラスメンバはコピーが1つしか存在しない。すべてのオブジェクトが同じ変数を共有する。 派生したクラスでも使用可能。
staticデータメンバは宣言しても、存在しないため、クラス外で定義しなければいけない。 デフォルトでは0に初期化される。
class myclass {
static int i;
};
int myclass::i;
int main()
{
return 0;
}
公開でstaticデータメンバを作成するとオブジェクトを介さずにスコープ演算子とクラス名でアクセス可能。
staticメンバ関数は同クラス内の他のstaticメンバ関数からでないとアクセスできない。
constメンバ関数は呼び出しもとのオブジェクトを修正できなくなる。 また非constメンバ関数を呼び出せない。逆に非constメンバ関数からの呼び出しは可能。
class X {
int i;
public:
int func() const;
};
mutableメンバはconstメンバ関数から修正することが可能。
class X {
mutable int i; //constメンバ関数から修正可能
public:
int func() const;
}
explicitコンストラクタは次の暗黙的な変換をしたくない時に使う。
class myclass {
public:
explicit myclass(int x) {}
};
myclass ob1(0);
myclass ob2 = 0; //コレはエラーになる
リンケージ指定子
extern "language" function-prototype;
複数の関数を一度にリンケージを指定したい場合
extern "language" {
function-prototype;
}
インラインアセンブラ
asm ("op-code");
一部のコンパイラでは次の形式もサポートされている。
asm op-code;
asm op-code
asm {
op-code
}
第14章
STL