C++をコンパイルしてみよう
C++はゲーム、組み込み、リアルタイム処理など、性能が重要な分野で使われます。GCCまたはClangなどのコンパイラを導入します。
#include <iostream>
int main() {
std::cout << "こんにちは、C++!\n";
return 0;
}g++ -std=c++17 -Wall -Wextra main.cpp -o app
./appこんにちは、C++!app.exeにし、.\app.exeで実行します。警告オプションは常に有効にしましょう。変数とデータ型
C++は変数の型を明示します。変更しない値はconstを付け、波括弧で初期化すると意図しない縮小変換を防げます。
std::string name{"Mity"};
int age{20};
double height{170.5};
bool is_student{true};
const int birth_month{8};
std::cout << name << "さん " << age << "歳\n";
std::cout << std::boolalpha << is_student << " " << birth_month << "月\n";Mityさん 20歳
true 8月std::stringを使うには#include <string>が必要です。変数を初期化せず読むと未定義動作になるため、宣言時に値を入れます。
入力と検証
std::cinは型に応じて入力を読みます。読み込み失敗をifで確認します。
int age{};
std::cout << "年齢: ";
if (std::cin >> age) {
std::cout << "来年は" << age + 1 << "歳です\n";
} else {
std::cout << "整数で入力してください\n";
}年齢: 20
来年は21歳です空白を含む一行はstd::getline(std::cin, text)で読みます。>>の後に併用するときは残った改行に注意が必要です。
演算子と条件分岐
整数同士の/は小数部分を切り捨てます。小数の結果が必要ならどちらかをdoubleにします。
int score{82};
if (score >= 80) {
std::cout << "合格(よくできました)\n";
} else if (score >= 60) {
std::cout << "合格\n";
} else {
std::cout << "再挑戦\n";
}合格(よくできました)繰り返し
forは初期化、条件、更新を指定します。whileは条件が真の間繰り返します。
for (int i{1}; i <= 5; ++i) {
std::cout << i << "回目\n";
}1回目
2回目
3回目
4回目
5回目size()で確認できます。vectorとmap
std::vectorは可変長の配列、std::mapはキーと値の組です。
std::vector<std::string> fruits{"りんご", "みかん"};
fruits.push_back("ぶどう");
std::map<std::string, int> scores{{"Aki", 82}, {"Mika", 91}};
for (const auto& fruit : fruits) {
std::cout << fruit << '\n';
}
std::cout << "Mika: " << scores.at("Mika") << "点\n";りんご
みかん
ぶどう
Mika: 91点at()はキーがないと例外を出します。存在確認にはfind()やC++20のcontains()を使います。
関数と参照
intのような小さな型は値渡しが適しています。一方、std::stringのような大きくなり得る値をコピーせず受け取るときはconst T&を使い、関数内で変更しない意図も示します。
std::string make_label(const std::string& name, int price) {
return name + ": " + std::to_string(price) + "円";
}
int main() {
std::string name{"ノート"};
std::cout << make_label(name, 180) << '\n';
}ノート: 180円nameはコピーされず参照として渡り、constによりmake_label内からは変更できません。この例には#include <string>と#include <iostream>が必要です。関数定義をmainより後ろに置く場合は、先に関数プロトタイプを宣言します。
例外とエラー
呼び出し側で回復可能な異常は例外で伝えられます。
double divide(double a, double b) {
if (b == 0) throw std::invalid_argument("0では割れません");
return a / b;
}
try {
std::cout << divide(10, 0) << '\n';
} catch (const std::invalid_argument& error) {
std::cout << error.what() << '\n';
}0では割れません#include <stdexcept>が必要です。検索結果がないなど通常起こり得る状態は、std::optionalで表す設計も検討します。
ファイルの読み書き
出力にstd::ofstream、入力にstd::ifstreamを使います。スコープを抜けると自動で閉じられます。
std::ofstream output{"memo.txt"};
if (!output) return 1;
output << "C++を学習中\n";
output.close();
std::ifstream input{"memo.txt"};
std::string line;
std::getline(input, line);
std::cout << line << '\n';C++を学習中#include <fstream>が必要です。オープン成功を確認し、利用者が指定したパスで意図しないファイルを上書きしないようにします。
クラスとカプセル化
クラスはデータと操作をまとめます。データをprivateにし、外部へ必要な操作だけをpublicで公開します。
class Product {
private:
std::string name_;
int price_;
public:
Product(std::string name, int price) : name_{std::move(name)}, price_{price} {}
void print() const { std::cout << name_ << ": " << price_ << "円\n"; }
};
Product product{"ノート", 180};
product.print();ノート: 180円std::moveには#include <utility>が必要です。初期化リストはメンバーを作成時に初期化します。
CMakeとテスト
ファイルが増えたらCMakeでビルド手順を記述します。ソースと別のフォルダーに生成物を置くアウトオブソースビルドが一般的です。
cmake_minimum_required(VERSION 3.16)
project(hello LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(hello main.cpp)cmake -S . -B build
cmake --build build
ctest --test-dir buildミニ課題:在庫管理
商品名、価格、在庫数を持つProductクラスを作り、std::vector<Product>から在庫金額を計算してください。
- 負の価格や在庫数を受け付けない
- 表示と計算を別の関数にする
-Wall -Wextraで警告がないことを確認する
次に学ぶこと
基礎を終えたら、リソースの所有権と標準ライブラリを深く学び、安全でテストしやすいコードへ進みましょう。
- STLアルゴリズム:
sort、find_if、transformでコレクションを処理する - スマートポインタ:
unique_ptrとshared_ptrで寿命と所有権を表す - Google Test:関数やクラスの振る舞いを自動確認する
- Boost:標準ライブラリを補う汎用ライブラリ群を必要に応じて学ぶ
まず在庫管理課題の検索や並べ替えをSTLアルゴリズムで書き換え、Google Testで通常値と境界値を確認すると、基礎から自然に発展できます。
