変数の宣言と定義について
C++の勉強(4)
前回のつづき.変数の「宣言」と「定義」について.
具体的な問題の詳細と正しい実装方法
全てのインスタンスで共通の列挙型変数enum Character {Cheerful, Gloomy}
をコンストラクタに与え,それによってインスタンスされたオブジェクトの状態が変わるようにしたかった.この場合には,この列挙型変数によってPerson
オブジェクトの性格が決まることになる.そこで,Person.hpp
で宣言されたクラスPerson
をインスタンス化する際に,main.cpp
に列挙型変数Character
の値を指定したい.これには,Person.hpp
のコストラクタを次のように定義すれば良い.
Person(Character character):_Char(character){ }
これにより,メンバー変数_Char
がコンストラクタに与えられた引数で初期化され,あるPerson
オブジェクトの性格が固定される.また,_Char
の値によってメンバ関数void Talk_To()
の反応が変わるようにPerson
クラスを改良すると以下のようになる.
これで,main
関数を次のようにする.
//main.cpp #include "Person.hpp" int main(){ Person *Anthony = new Person(Cheerful); std::cout << "Anthony said, " << std::endl; Anthony->Talk_To(); std::cout << "Ben said, " << std::endl; Person *Ben = new Person(Gloomy); Ben->Talk_To(); delete Anthony; delete Ben; return 0; }
コンパイル・実行すると次の結果になる.
Anthony said, Hey bro! Ben said, Ah... Hi...
Person
クラスの一つ目のオブジェクトであるAnthonyは性格_Char
が明るいCheerful
陽キャなので元気に反応するが,Benは暗いGloomy
なので反応も暗い.
うまくコンパイルができなかった原因
はじめに,「宣言」と「定義」の違いがわからなかったことが原因でコンパイルできなかったと言ったが,それはenum
の仕様を理解していなかったことも原因の一つだった.前回の記事に書いたように,Person.hpp
の最初にあるenum Character {Cheerful, Gloomy}
は「宣言」である.このため,ファイル分割の規則(宣言はヘッダファイルに,定義はソースファイルに)に則ってヘッダファイルに書いている.しかし,使い始めた当初は「宣言」と「定義」の違いがわからずに,とりあえずいろいろなファイルに列挙型変数Character
の存在を知らしめたかったので,extern enum Character {Cheerful, Gloomy}
としていた.が,extern
はある変数の「定義」を外部のファイルにも知らしめるたものもので,「宣言」であるenum ...
に対して使えないからコンパイルエラーがでていたのである.これを修正した上のPerson
クラスは仕様どおりに正常に動く.
まとめ
enum 型名 {値1, 値2, ...} 変数名
で列挙型型名
を宣言し,変数名
を定義することができる.- ファイル分割の際にはヘッダファイルに宣言を書き,ソースファイルに定義を書くと見通しが良い.
main.cpp
でAnthony, Ben
をdelete
しなくてはならなかったのが心苦しかった.