ここまで学んだ「クラス」「コンストラクタ」「アクセス修飾子」をしっかり理解するため、コピー元コードを改良する演習問題を提示します。新しい知識は不要なので、これまでの復習として取り組みましょう。
次のコードについて、a.balance = -100; のような外部からの不正アクセスを防ぐには何をすればよいですか?
class Account {
public:
int balance;
void deposit(int amount) { balance += amount; }
};
private にすることでクラス外部からの直接アクセスを禁止できます(カプセル化)。操作は deposit() などのメソッド経由にします。これにより不正な値の設定を防げます。
次のコードを実行したとき、何が表示されますか?
#include <iostream>
using namespace std;
class Account {
private:
int balance;
public:
Account(int initial) : balance(initial) {}
bool paycheck(int amount) { return balance >= amount; }
void pay(int amount) { balance -= amount; cout << amount << "円出金" << endl; }
void show() { cout << "残高: " << balance << "円" << endl; }
};
int main() {
Account a(500);
if (a.paycheck(200)) a.pay(200);
else cout << "出金失敗" << endl;
a.show();
return 0;
}
paycheck(200) は 500 >= 200 が true なので pay(200) が呼ばれます。残高は 500 - 200 = 300 円になります。出力は "200円出金" → "残高: 300円" です。
次のコードで r.width = 10; のような行は必要でしょうか?
class Rectangle {
public:
int width;
int height;
int area() { return width * height; }
};
int main() {
Rectangle r;
r.width = 5;
r.height = 3;
cout << r.area() << endl;
}
width・height を private にすることで、外部から不正な値を設定されるリスクがなくなります。これがカプセル化の考え方です。
次のコードの実行結果はどれですか?
#include <iostream>
using namespace std;
class Product {
private:
string name;
int price;
public:
Product(string n, int p) : name(n), price(p) {}
void show() { cout << name << " は " << price << " 円です。" << endl; }
};
int main() {
Product p("みかん", 80);
p.show();
return 0;
}
name("みかん")、price(80) と設定されます。show() はクラスのメンバ関数なので private メンバにアクセスでき、"みかん は 80 円です。" と出力されます。
// account.cpp(元のコード)
#include <iostream>
using namespace std;
class Account {
public:
int balance;
void deposit(int amount) {
balance += amount;
}
void show() {
cout << "残高: " << balance << "円" << endl;
}
};
int main() {
Account a;
a.balance = 0;
a.deposit(500);
a.show();
return 0;
}
改善指示:
balance を private にするdeposit() と show() はそのまま使えるようにするpay(int) 関数を作るbool paycheck(int) 関数を作るmain() で残高500円からスタートし、出金可能なら支払いし、そうでなければ失敗メッセージを表示し、最後に残高を表示する// 15_account_refactor.cpp
#include <iostream>
using namespace std;
class Account {
private:
int balance;
public:
Account(int initial) {
balance = initial;
}
void deposit(int amount) {
balance += amount;
}
void pay(int amount) {
balance -= amount;
cout << amount << "円を出金しました。" << endl;
}
bool paycheck(int amount) {
return balance >= amount;
}
void show() {
cout << "残高: " << balance << "円" << endl;
}
};
int main() {
Account a(500);
a.deposit(300);
if (a.paycheck(200)) {
a.pay(200);
} else {
cout << "200円の出金に失敗しました。" << endl;
}
if (a.paycheck(700)) {
a.pay(700);
} else {
cout << "700円の出金に失敗しました。" << endl;
}
a.show();
return 0;
}
解説balance を private にしてカプセル化しました。出金可能性を事前に paycheck() で判定し、if 文で分岐する構造としました。
// rectangle.cpp(元のコード)
#include <iostream>
using namespace std;
class Rectangle {
public:
int width;
int height;
int area() {
return width * height;
}
};
int main() {
Rectangle r;
r.width = 5;
r.height = 3;
cout << "面積: " << r.area() << endl;
return 0;
}
改善指示:
width と height を private に変更するarea() 関数はそのまま使えるようにするmain() でデフォルトサイズとサイズ指定の両方のオブジェクトを生成して面積を表示する// 15_rectangle_refactor.cpp
#include <iostream>
using namespace std;
class Rectangle {
private:
int width;
int height;
public:
Rectangle() : width(1), height(1) {}
Rectangle(int w, int h) : width(w), height(h) {}
int area() {
return width * height;
}
};
int main() {
Rectangle r1;
Rectangle r2(5, 3);
cout << "r1の面積: " << r1.area() << endl;
cout << "r2の面積: " << r2.area() << endl;
return 0;
}
// product.cpp(元のコード)
#include <iostream>
using namespace std;
class Product {
public:
string name;
int price;
void show() {
cout << name << " は " << price << " 円です。" << endl;
}
};
int main() {
Product p;
p.name = "りんご";
p.price = 150;
p.show();
return 0;
}
改善指示:
name と price を private に変更するshow() 関数はそのまま使えるようにするmain() でインスタンスを生成し、正しく表示されることを確認する// 15_product_refactor.cpp
#include <iostream>
using namespace std;
class Product {
private:
string name;
int price;
public:
Product(string n, int p) : name(n), price(p) {}
void show() {
cout << name << " は " << price << " 円です。" << endl;
}
};
int main() {
Product p("りんご", 150);
p.show();
return 0;
}
private にすることで外部からの不正アクセスを防ぐ(カプセル化)