関数にポリモーフィズム(多態性)をもたせて動作を観察してみましょう
ソーラー「
まず1つの親クラスGameCharacterと
親クラスGameCharacterのメンバ変数宣言、メンバ関数宣言を
継承した
子クラスを
3つ用意します
最初に
親クラスGameCharacterのクラス宣言と
親クラスGameCharacterのメンバ関数statusDataDisplay()
の定義を
👇
____________________________________
class GameCharacter {
public:
string name;
int HP;
int MP;
void statusDataDisplay();
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
____________________________________
として
1つ目の
子クラスである
Humanのクラス宣言と
子クラスHumanのメンバ関数
statusDataDisplay()
の定義を
👇
_____________________________________________________________________
class Human :public GameCharacter {
public:
int TP;//👈Human(人間)型のキャラクターだけに備わっているテクニックポイントです
void statusDataDisplay();//🌞メンバ関数statusDataDisplay()のオーバーライドを行っています
void Human::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "TP " << TP << "\n";
}
____________________________________
とします。」
2つ目の
子クラスである
Dragonのクラス宣言と
子クラスDragonのメンバ関数
statusDataDisplay()
の定義を
👇
_____________________________________________________________________
class Dragon :public GameCharacter {
public:
int DP;//👈ドラゴン型のキャラクターだけに備わっているドラゴンポイントです
void statusDataDisplay();
};
//👇🌞🌞🌞クラスDragonのメンバ関数statusDataDisplay() の定義です🌞🌞🌞
void Dragon::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
}
____________________________________
とします。」
ソーラー「
3つ目の
子クラスである
Elfのクラス宣言と
子クラスElfのメンバ関数
statusDataDisplay()
の定義を
👇
_____________________________________________________________________
class Elf:public GameCharacter {
public:
int EP;//👈エルフ型のキャラクターだけに備わっているエルフポイントです
void statusDataDisplay();
//親クラスGameCharacterのメンバ関数statusDataDisplay()をオーバーライドしています
};
//👇🌞🌞🌞クラスElfのメンバ関数statusDataDisplay() の定義です🌞🌞🌞
void Elf::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "EP " << EP << "\n";
}
____________________________________
とします。」
これらのクラスが用いられたプログラムをご覧ください
👇
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
class GameCharacter {
public:
string name;
int HP;
int MP;
virtual void statusDataDisplay();//👈🌞🌞🌞仮想関数に設定されています virtualをつけただけです
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
class Human :public GameCharacter {
public:
int TP;//👈Human(人間)型のキャラクターだけに備わっているテクニックポイントです
void statusDataDisplay();//🌞メンバ関数statusDataDisplay()のオーバーライドを行っています
};
//👇🌞🌞🌞クラスHumanのメンバ関数statusDataDisplay() の定義です🌞🌞🌞
void Human::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "TP " << TP << "\n";
}
class Dragon :public GameCharacter {
public:
int DP;//👈ドラゴン型のキャラクターだけに備わっているドラゴンポイントです
void statusDataDisplay();
};
//👇🌞🌞🌞クラスDragonのメンバ関数statusDataDisplay() の定義です🌞🌞🌞
void Dragon::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
}
class Elf :public GameCharacter {
public:
int EP;//👈エルフ型のキャラクターだけに備わっているエルフポイントです
void statusDataDisplay();
//親クラスGameCharacterのメンバ関数statusDataDisplay()をオーバーライドしています
};
//👇🌞🌞🌞クラスElfのメンバ関数statusDataDisplay() の定義です🌞🌞🌞
void Elf::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "EP " << EP << "\n";
}
int main() {
Human Lyliane;
Lyliane.name = "リリアーネ";
Lyliane.HP = 10;
Lyliane.MP = 5;
Lyliane.TP = 7;
Dragon Pokky;
Pokky.name = "ポッキー";
Pokky.HP = 20;
Pokky.MP = 3;
Pokky.DP = 2;
Elf Sylphy;
Sylphy.name = "シルフィ";
Sylphy.HP = 3;
Sylphy.MP = 18;
Sylphy.EP = 3;
GameCharacter* pta;
pta=&Lyliane;
pta->statusDataDisplay();
pta =&Pokky;
pta->statusDataDisplay();
pta =&Sylphy;
pta->statusDataDisplay();
return 0;
}
プログラムの実行結果
リリアーネ
HP 10
MP 5
TP 7
ポッキー
HP 20
MP 3
DP 2
シルフィ
HP 3
MP 18
EP 3
ソーラー「このプログラムの
GameCharacter* pta;
pta=&Lyliane;
pta->statusDataDisplay();
pta =&Pokky;
pta->statusDataDisplay();
pta =&Sylphy;
pta->statusDataDisplay();
に御注目下さい
ptaの親クラスGameCharacter*型のポインタ変数宣言
GameCharacter* pta;
により
生成される
親クラスGameCharacter*型のポインタ変数であるptaに
子クラスHuman型のオブジェクトLylianeのアドレス&Lyliane
子クラスDragon型のオブジェクトPokkyのアドレス&Pokky
子クラスElf型のオブジェクトSylphyのアドレス&Sylphy
を
代入することができています
親クラスGameCharacter*型のポインタ変数ptaに
子クラスHuman型のオブジェクトLylianeのアドレス&Lyliane
子クラスDragon型のオブジェクトPokkyのアドレス&Pokky
子クラスElf型のオブジェクトSylphyのアドレス&Sylphy
が代入されると
GameCharacter* pta
には
あたかも
親クラスGameCharacter型のオブジェクトLylianeのアドレス&Lyliane
親クラスGameCharacter型のオブジェクトPokkyのアドレス&Pokky
親クラスGameCharacter型のオブジェクトSylphyのアドレス&Sylphy
が代入されているような感じになります
いえ 😊正確には
親クラスGameCharacter*型のポインタ変数ptaに
子クラスHuman型のオブジェクトLylianeの(親クラスから引き継いだ)メンバ変数
と
子クラスHuman型のオブジェクトLylianeの(親クラスから引き継いだ)メンバ関数
の管理しているメモリ
を代表して管理しているアドレス&Lyliane
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
と
子クラスHuman型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
の管理しているメモリ
を代表して管理しているアドレス&Pokky
子クラスElf型のオブジェクトSylphyの(親クラスから引き継いだ)メンバ変数
と
子クラスElf型のオブジェクトSylphyの(親クラスから引き継いだ)メンバ関数
の管理しているメモリ
を代表して管理しているアドレス&Sylphy
が代入されることになります
このとき
親クラスGameCharacter*型のポインタ変数ptaは
ptaという同じ名前で
親クラスGameCharacter型のオブジェクトLylianeのアドレス&Lyliane
親クラスGameCharacter型のオブジェクトPokkyのアドレス&Pokky
親クラスGameCharacter型のオブジェクトSylphyのアドレス&Sylphy
をあらわすことになります
このことを
ポリモーフィズム(多態性)
と呼びます
そして
pta =&Lyliane;
pta->statusDataDisplay();
が実行されると
GameCharacter* ptaに
子クラスHuman型のオブジェクトLylianeの(親クラスGameCharacterから引き継いだ)メンバ変数
Lyliane.name
Lyliane.HP
Lyliane.MP
と
子クラスHuman型のオブジェクトLylianeの(親クラスから引き継いだ)メンバ関数
Lyliane.statusDataDisplay()
の管理しているメモリ
を代表しているアドレス
&Lyliane
が代入されているので
pta->statusDataDisplay();
が実行されるとき
(親クラスから引き継いだ)メンバ関数statusDataDisplay()
の定義が用いられそうですが
このとき
親クラスGameCharacterのメンバ関数statusDataDisplay()は
😊😊😊仮想関数😊😊😊であり
子クラスHumanのメンバ関数statusDataDisplay()によって
オーバーライドされているので
子クラスHumanに元から備わっているメンバ関数statusDataDisplay()
の定義が用いられることになります
ですので
pta->statusDataDisplay();
が実行されると
子クラスHumanのメンバ関数statusDataDisplay()の定義
void Human::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "TP " << TP << "\n";
}
の
name
HP
MP
TP
に
Lyliane.name
Lyliane.HP
Lyliane.MP
Lyliane.TP
が代入されたものが実行され
リリアーネ
HP 10
MP 5
TP 7
が表示されることになります
☆ちょっとおまけ
子クラスHuman型のオブジェクトLylianeの(子クラスHumanに元から備わっている)メンバ関数
Lyliane.statusDataDisplay()は
子クラスHuman型のオブジェクトLylianeの(子クラスHumanに元から備わっている)メンバ変数
Lyliane.TPにアクセスすることができます☆
そして
pta =&Pokky;
pta->statusDataDisplay();
が実行されると
GameCharacter* ptaに
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
と
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
の管理しているメモリ
を代表しているアドレス
&Pokky
が代入されているので
pta->statusDataDisplay();
が実行されるとき
(親クラスから引き継いだ)メンバ関数statusDataDisplay()
の定義が用いられそうですが
このとき
親クラスGameCharacterのメンバ関数statusDataDisplay()は
😊😊😊仮想関数😊😊😊であり
子クラスDragonのメンバ関数statusDataDisplay()によって
オーバーライドされているので
子クラスDragonに元から備わっているメンバ関数statusDataDisplay()
の定義が用いられることになります
ですので
pta->statusDataDisplay();
が実行されると
子クラスDragonのメンバ関数statusDataDisplay()の定義
void Dragon::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
}
の
name
HP
MP
DP
に
Pokky.name
Pokky.HP
Pokky.MP
Pokky.TP
が代入されたものが実行され
ポッキー
HP 20
MP 3
DP 2
が表示されることになります
☆ちょっとおまけ
子クラスDragon型のオブジェクトPokkyの(子クラスDragonに元から備わっている)メンバ関数
Pokky.statusDataDisplay()は
子クラスDragon型のオブジェクトPokkyの(子クラスDragonに元から備わっている)メンバ変数
Pokky.DPにアクセスすることができます☆
そして
pta =&Sylphy;
pta->statusDataDisplay();
が実行されると
GameCharacter* ptaに
親クラスGameCharacter型のオブジェクトSylphyのアドレス&Sylphyが代入されているので
pta->statusDataDisplay();
が実行されるとき
pta->
は
親クラスGameCharacterのメンバ関数statusDataDisplay()
にアクセスすることになりそうですが
このとき
親クラスGameCharacterのメンバ関数statusDataDisplay()は
😊😊😊仮想関数😊😊😊であり
子クラスElfのメンバ関数statusDataDisplay()によって
オーバーライドされているので
pta->は
子クラスElfのメンバ関数statusDataDisplay()にアクセスすることになります
ですので
pta->statusDataDisplay();
が実行されると
子クラスElfのメンバ関数statusDataDisplay()の定義
void Elf::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "EP " << EP << "\n";
}
の
name
HP
MP
EP
に
Sylphy.name
Sylphy.HP
Sylphy.MP
Sylphy.EP
が代入されたものが実行され
シルフィ
HP 3
MP 18
EP 3
が表示されることになります
つまり
pta->statusDataDisplay()
は
名前は同じでも
異なる子クラス型のオブジェクトの異なる子クラスのメンバ関数
をあらわしています
pta->statusDataDisplay()
は
ポリモーフィズム(多態性)
を備えているというわけです
もう1つポリモーフィズム(多態性)が用いられているプログラムをご覧ください
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
class GameCharacter {
public:
string name;
int HP;
int MP;
virtual void statusDataDisplay();//🌞ここにvirtualをつけただけです
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
class Human :public GameCharacter {
public:
int TP;//👈Human(人間)型のキャラクターだけに備わっているテクニックポイントです
void statusDataDisplay();//🌞メンバ関数statusDataDisplay()のオーバーライドを行っています
void scanGameCharacterData(GameCharacter* pta);
};
//👇🌞🌞🌞クラスHumanのメンバ関数statusDataDisplay() の定義です🌞🌞🌞
void Human::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "TP " << TP << "\n";
}
//👇🌞🌞🌞クラスHumanのメンバ関数scanGameCharacterData(GameCharacter* pta)の定義です🌞🌞🌞
void Human::scanGameCharacterData(GameCharacter* pta) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << pta->name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
pta->statusDataDisplay();
}
class Dragon :public GameCharacter {
public:
int DP;//👈ドラゴン型のキャラクターだけに備わっているドラゴンポイントです
void statusDataDisplay();
};
//👇🌞🌞🌞クラスDragonのメンバ関数statusDataDisplay() の定義です🌞🌞🌞
void Dragon::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
}
class Elf :public GameCharacter {
public:
int EP;//👈エルフ型のキャラクターだけに備わっているエルフポイントです
void statusDataDisplay();
//親クラスGameCharacterのメンバ関数statusDataDisplay()をオーバーライドしています
};
//👇🌞🌞🌞クラスElfのメンバ関数statusDataDisplay() の定義です🌞🌞🌞
void Elf::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "EP " << EP << "\n";
}
int main() {
Human Lyliane;
Lyliane.name = "リリアーネ";
Lyliane.HP = 10;
Lyliane.MP = 5;
Lyliane.TP = 7;
Dragon Pokky;
Pokky.name = "ポッキー";
Pokky.HP = 20;
Pokky.MP = 3;
Pokky.DP = 2;
Elf Sylphy;
Sylphy.name = "シルフィ";
Sylphy.HP = 3;
Sylphy.MP = 18;
Sylphy.EP = 3;
Lyliane.scanGameCharacterData(&Pokky);
Lyliane.scanGameCharacterData(&Sylphy);
Lyliane.scanGameCharacterData(&Lyliane);
return 0;
}
ビルド実行結果
スキャン発動!
リリアーネはポッキーのスキャンを開始した
ステータスデータ
ポッキー
HP 20
MP 3
DP 2
スキャン発動!
リリアーネはシルフィのスキャンを開始した
ステータスデータ
シルフィ
HP 3
MP 18
EP 3
スキャン発動!
リリアーネはリリアーネのスキャンを開始した
ステータスデータ
リリアーネ
HP 10
MP 5
TP 7
ソーラー「このプログラムの
Lyliane.scanGameCharacterData(&Pokky);
Lyliane.scanGameCharacterData(&Sylphy);
Lyliane.scanGameCharacterData(&Lyliane);
に御注目下さい
クラスHumanのメンバ関数scanGameCharacterData(GameCharacter* pta)の定義
👇
void Human::scanGameCharacterData(GameCharacter* pta) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << pta->name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
pta->statusDataDisplay();
}
👆
の
引数部分に
GameCharacter* pta
すなわち
親クラスGameCharacter*型のポインタ変数ptaをもちいているので
子クラスDragon型のオブジェクトPokkyのアドレス&Pokky
子クラスElf型のオブジェクトSylphyのアドレス&Sylphy
子クラスHuman型のオブジェクトLylianeのアドレス&Lyliane
を
引数部分の
GameCharacter* pta
に代入することができています
親クラスGameCharacter*型のポインタ変数ptaに
子クラスDragon型のオブジェクトPokkyのアドレス&Pokky
子クラスElf型のオブジェクトSylphyのアドレス&Sylphy
子クラスHuman型のオブジェクトLylianeのアドレス&Lyliane
が代入されると
GameCharacter* pta
には
親クラスGameCharacter型のオブジェクトPokkyのアドレス&Pokky
親クラスGameCharacter型のオブジェクトSylphyのアドレス&Sylphy
親クラスGameCharacter型のオブジェクトLylianeのアドレス&Lyliane
が代入されていることになります
このとき
GameCharacter型のポインタ変数ptaは
同じ名前で
親クラスGameCharacter型のオブジェクトPokkyのアドレス&Pokky
親クラスGameCharacter型のオブジェクトSylphyのアドレス&Sylphy
親クラスGameCharacter型のオブジェクトLylianeのアドレス&Lyliane
をあらわしています
これも
ポリモーフィズム(多態性)
の一種ですね
そして
Lyliane.scanGameCharacterData(&Pokky);
が実行されると
クラスHumanのメンバ関数scanGameCharacterData(GameCharacter* pta)の定義
👇
void Human::scanGameCharacterData(GameCharacter* pta) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << pta->name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
pta->statusDataDisplay();
}
👆
の
nameにLyliane.name
pta->nameにPokky.name
が代入されたものが
まず
実行されることになります
そして
GameCharacter* ptaに
親クラスGameCharacter型のオブジェクトPokkyのアドレス&Pokkyが代入されているので
pta->statusDataDisplay();
が実行されるとき
pta->
は
親クラスGameCharacterのメンバ関数statusDataDisplay()
にアクセスすることになりそうですが
このとき
親クラスGameCharacterのメンバ関数statusDataDisplay()は
😊😊😊仮想関数😊😊😊であり
子クラスDragonのメンバ関数statusDataDisplay()によって
オーバーライドされているので
pta->は
子クラスDragonのメンバ関数statusDataDisplay()にアクセスすることになります
ですので
pta->statusDataDisplay();
が実行されると
子クラスDragonのメンバ関数statusDataDisplay()の定義
void Dragon::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
}
の
name
HP
MP
DP
に
Pokky.name
Pokky.HP
Pokky.MP
Pokky.DP
が代入されたものが実行され
スキャン発動!
リリアーネはポッキーのスキャンを開始した
ステータスデータ
ポッキー
HP 20
MP 3
DP 2
が表示されることになります
そして
Lyliane.scanGameCharacterData(&Sylphy);
が実行されると
クラスHumanのメンバ関数scanGameCharacterData(GameCharacter* pta)の定義
👇
void Human::scanGameCharacterData(GameCharacter* pta) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << pta->name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
pta->statusDataDisplay();
}
👆
の
nameにLyliane.name
pta->nameにSylphy.name
が代入されたものが
まず
実行されることになります
そして
GameCharacter* ptaに
親クラスGameCharacter型のオブジェクトSylphyのアドレス&Sylphyが代入されているので
pta->statusDataDisplay();
が実行されるとき
pta->
は
親クラスGameCharacterのメンバ関数statusDataDisplay()
にアクセスすることになりそうですが
このとき
親クラスGameCharacterのメンバ関数statusDataDisplay()は
😊😊😊仮想関数😊😊😊であり
子クラスElfのメンバ関数statusDataDisplay()によって
オーバーライドされているので
pta->は
子クラスElfのメンバ関数statusDataDisplay()にアクセスすることになります
ですので
pta->statusDataDisplay();
が実行されると
子クラスElfのメンバ関数statusDataDisplay()の定義
void Elf::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "EP " << EP << "\n";
}
の
name
HP
MP
EP
に
Sylphy.name
Sylphy.HP
Sylphy.MP
Sylphy.EP
が代入されたものが実行され
スキャン発動!
リリアーネはシルフィのスキャンを開始した
ステータスデータ
シルフィ
HP 3
MP 18
EP 3
が表示されることになります
そして
Lyliane.scanGameCharacterData(&Lyliane);
が実行されると
クラスHumanのメンバ関数scanGameCharacterData(GameCharacter* pta)の定義
👇
void Human::scanGameCharacterData(GameCharacter* pta) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << pta->name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
pta->statusDataDisplay();
}
👆
の
nameにLyliane.name
pta->nameにLyliane.name
が代入されたものが
まず
実行されることになります
そして
GameCharacter* ptaに
親クラスGameCharacter型のオブジェクトLylianeのアドレス&Lylianeが代入されているので
pta->statusDataDisplay();
が実行されるとき
pta->
は
親クラスGameCharacterのメンバ関数statusDataDisplay()
にアクセスすることになりそうですが
このとき
親クラスGameCharacterのメンバ関数statusDataDisplay()は
😊😊😊仮想関数😊😊😊であり
子クラスHumanのメンバ関数statusDataDisplay()によって
オーバーライドされているので
pta->は
子クラスHumanのメンバ関数statusDataDisplay()にアクセスすることになります
ですので
pta->statusDataDisplay();
が実行されると
子クラスHumanのメンバ関数statusDataDisplay()の定義
void Human::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "TP " << TP << "\n";
}
の
name
HP
MP
TP
に
Lyliane.name
Lyliane.HP
Lyliane.MP
Lyliane.TP
が代入されたものが実行され
スキャン発動!
リリアーネはリリアーネのスキャンを開始した
ステータスデータ
リリアーネ
HP 10
MP 5
TP 7
が表示されることになります
つまり
pta->statusDataDisplay()
は
名前は同じでも
ptaに代入されるアドレスによって
異なる子クラス型のオブジェクトの異なる子クラスのメンバ関数
をあらわしています
pta->statusDataDisplay()
は
ポリモーフィズム(多態性)
を備えているというわけです」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます