hiziriAI’s blog

自分用雑記

C++ 記法

C++

C言語は分かっているものとして書いているので、変数の宣言なんかは説明しない。 自分向け。 参考文献は、猫でもわかる C++プログラミング

ライブラリのインクルード

#include <iostream>

Cのライブラリは、xxx.hならcxxxとしてインクルードできる。

ネームスペース

using namespace std;

  • Integer
    • short
    • int
    • long
  • Floating Point
    • float
    • double
    • long double
  • Char
    • char
  • Boolean
    • bool
      • true
      • false

制御構文

for

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

初期化部で変数宣言が可能に

関数

プロトタイプ宣言

int add(int);

引数の指定は型名だけで十分

デフォルト値

int func(int a = 100, int b = 100){
...
}

引数が渡されなかった場合、指定した値が使われる。 関数プロトタイプ宣言のときは、プロトタイプ宣言でデフォルト値を指定する。

int func(int = 10, int = 3);

...

int func(int a, int b){
...
}

オーバーロード

引数の個数や型が異なれば同じ名前の関数を定義できる。 ただし、戻り値だけが異なる場合は同じものと見做される。 デフォルト引数を取る同名の関数との間で分かりづらいコンパイルエラーや動作を引き起しうる。 同時に使用しないようにするべき。

const

引数にconstを付けると

記憶クラス指定子

  • static
    • プログラム終了まで同一の参照を保持する
  • extern
    • 別ファイルで宣言された変数を参照したいときに
  • auto
    • 自動変数はスタック領域に保存される、ブロック内で有効
    • たんなるローカル変数
  • register

ポインタ

参照

別名を付けられる

int a;
int &alias = a;

/*
 int a;
 int &alias;
 alias = a;
 error
 */

変更は元の引数にも反映される 関数を呼び出した先でも同じことができる

関数の呼び出し先で変数の値を変更して欲しくないときは、constを付ける

メモリ

動的確保

int *a;
a = new int[4]; // malloc
delete [] a; // free

クラス

宣言

class Test {
private:
  char* private_name = "private";
  char* privateFunc() {
    return private_name;
  }
  
public:
  char* public_name = "public";
  void printPrivate(){
    std::cout << private_name << endl;
    return;
  }

  void callPrivate(){
    std::cout << privateFunc() << endl;
    return;
  }
};

次の様に関数の中身を分離できる。

class Test {
private:
  char* private_name = "private";
  char* privateFunc();
  
public:
  char* public_name = "public";
  void printPrivate();
  void callPrivate();
};

char* Test::privateFunc(){
  return private_name;
}

void Test::printPrivate(){
  std::cout << private_name << endl;
  return;
}

void Test::callPrivate(){
  std::cout << privateFunc() << endl;
  return;
}

inlineを付ければ、クラス内に書いたのと同じ扱いになる。

変数宣言

Test t;

コンストラクタ

コンストラクタはオーバロードできる

引数なし

class Const {
public:
  int a;
  Const();
};

Const::Const() {
  a = 100;
}

int main(){
  Const c;
  std::cout << c.a << endl;
  return 0;
}

引数あり

class Const {
public:
  int a;
  Const(int);
};

Const::Const(int i) {
  a = i;
}

int main(){
  Const c(101);
  std::cout << c.a << endl;
  return 0;
}

コピーコンストラクタ

代入の際には、tのコピーコンストラクタが呼ばれる

Test t;
Test t_copy = t;

定義は以下

class Test {
public:
  int* array = {0, 1, 2, 3, 4, 5};
  Test();
  Test(const Test &t);
};

Test::Test(){
  array[0] = 10;
}

Test::Test(const Test &t){
  array[0] = t.array[0];
}

自分と同じ型の参照を受け取るコンストラクタとして実装される

デストラクタ

class Test {
public:
  Test();
  ~Test(); // destractor
}

thisポインタ

メンバ関数内で、自分自身への参照を保持する

static

クラス関数、クラス変数を定義する

メンバポインタ

int x::*ptr;
ptr = &x::a;

継承

class Parent {
private:
  int p = 1;
protected:
  int protect = 2;
public:
  int pub = 3; 
};

class Child : public Parent {
    ...
}
コンストラクタ

コンストラクタを指定する

Test() : Base(4) {
    ...
}
仮想関数

virtualと付ける こうすると、ポインタが実際に指している型のメンバにアクセスできる

純仮想関数

virtual funcName = 0; 抽象クラスのような使い方

フレンド関数

friendと付けて指定する。 クラス内で定義することで、そのクラスの非公開メンバにアクセスすることのできる関数を指定する friend int funcName(int arg);

フレンドクラス

クラスA内で定義する

friend class B;

B内ではAの非公開メンバにアクセスできる。 Bを継承したクラスではB経由でAにアクセスすることはできるが、Aに直接アクセスすることはできない。

多重継承

できる

菱形継承

できる

演算子オーバーロード

予約語operatorを使う 加算はこんな感じ int operator + (int a, int b){return a + b}

代入演算子も複合代入演算子オーバーロードできる。 メンバ関数として宣言することも、通常の関数としても宣言でき、中置記法で記述できる。

フレンド関数

通常の関数として宣言し、クラス内でフレンド関数としておけば、非公開メンバへのアクセスもしやすい。

単項演算子

クラス内では引数なしの関数のように宣言するとできる。

インクリメンタル

Vector:operator ++();
Vector:operator ++(int);

ファイルI/O

lib-fstream

#include <fstream>

int main(){
    ofstream of;
    of.open("filename", ios:app) // append
    if(!of)
        return -1;
    of << "test" << endl;
    of.close();
    
    return 0;
}

テンプレート

型抽象化 予約語templateを使う template <typename T> return-type funcname(args){......}

テンプレートクラス

同様 typeidを使うと、現在の型が分かる

標準テンプレートライブラリ

例外処理

try{
    if(...)
        throw val;      
} catch(type <val-name>) {
    error-handling
}

ラムダ式

[]でラムダ式の宣言を始める。 続いて引数、返り値の型(省略可能)、関数本体を定義する。 呼び出すときは通常の関数のように引数を渡す。

int main(){
  [](int a, int b) -> int {return a + b;}(1, 3);

  return 0;
}

の中に&を付けると、スコープ内の変数を参照として補足する。 =を付けると、値をコピーする。=を付けたとき、引数の()の後にmutableと付けると、補足した変数を変更できるようになる。ただし、参照元は変更されない。 の中では、変数ごとに参照かコピーかを決定できる。参照の場合は&を変数名のあとに付ける。