C++ using 書いて覚えるための初心者自己中記事
この記事で勉強したusing をもっと勉強するらしい。
まずこれを、
#include <iostream> namespace Hoge { using namespace std; } int main() { Hoge::cout << "hello" << Hoge::endl; system("pause"); }
見たことない書き方。
新しい出会い。
#include <iostream> namespace Hoge { using namespace std; void Hello() { cout << "hello" << endl; } } int main() { Hoge::Hello(); system("pause"); }
これも可能。
名前空間内でusing すると対象の名前空間はusing された場所の名前空間に取り込まれる。
取り込んで相手の能力を吸収。カービィかな?
using == カービィ
trueだな
で覚えよう。
いままでずっと使ってきたmain 関数の外、グローバル部分へのusingは
グローバルカービィにstd を吸わせていたのか。
グローバルカービィ
Hoge内で using namespace std; を書くと
coutは
std::cout であり、また
Hoge::cout でもある。
名前空間スコープに限った話ではなくブロックスコープでも同じ。
次に
class Show { public: static void Value(char ch) {//Show2 でオーバーロードライドされた cout << ch << endl; } static void Value(const char* str) { cout << str << endl; } }; class Show2 :public Show{ public: static void Value(char ch) {//文字コードを出す仕様にした int n = static_cast<unsigned char>(ch); cout << n << endl; } }; //静的メンバ関数はクラスのオブジェクトが無くても呼び出せる int main() { Show2::Value('A'); Show2::Value("Hoge");//使用できない。エラー system("pause"); }
基底クラスでは引数が違う同名のメンバ関数があり
派生クラスではそのメンバ関数のうちの一つをオーバーロードライド。
この状態で派生クラスに対して2種類の引数のメンバ関数をそれぞれ呼び出す。
片方はShow2 でオーバーロードライドされたメンバ関数が呼び出された。
もう片方はオーバーロードライドされていないのでShowのメンバ関数が呼び出されると思いきやエラーになる。
これは、そのまま
このような状態だと基底クラスのメンバ関数Show は全て使えなくなるらしい。
全て使えなくなるというと、俺は勘違いしてしまう。
Show2::Value('A'); Show::Value("Hoge");//直接指定すれば使える //Show2::Value("Hoge");//使用できない。エラー
直接呼び出せばもちろん使えるのだ。
・・・あれ?
オーバーロードとオーバーライドって違うか?
ちょっと確認。
class Show { public: static void Value(char ch) {//引数の違う同名関数 オーバーロード cout << ch << endl; } static void Value(const char* str) {//引数の違う同名関数 オーバーロード cout << str << endl; } }; class Show2 :public Show{ public: static void Value(char ch) {//Showの同名メンバ関数を上書き オーバーライド int n = static_cast<unsigned char>(ch); cout << n << endl; } };
引数の違う同名関数
-> オーバーロード
派生クラスで基底クラスのメンバ関数を処理を変更して上書き
-> オーバーライド
よし。
上の文章で間違ってたから直した。
つづき、
オーバーライドされていない基底クラスのShow関数まで使えなくなってしまうので困ってた。
これは基底クラスのすべてのオーバーロードされたShow関数を派生クラスでオーバーライドすれば一応解決する。
オーバーライドした関数内で基底クラスのShow関数を呼び出す。みたいな。
しかし、using を使えばもっとスマートに解決できるらしい。
(やっとusing来た)
class Show { public: static void Value(char ch) {//引数の違う同名関数 オーバーロード cout << ch << endl; } static void Value(const char* str) {//引数の違う同名関数 オーバーロード cout << str << endl; } }; class Show2 :public Show{ public: static void Value(char ch) {//Showの同名メンバ関数を上書き オーバーライド int n = static_cast<unsigned char>(ch); cout << n << endl; } using Show::Value; //ここでusing }; //静的メンバ関数はクラスのオブジェクトが無くても呼び出せる int main() { Show2::Value('A'); Show::Value("Hoge"); Show2::Value("Hoge");//使えるようになった system("pause"); }
using Show::Value; //ここでusing
さらにこのusing はアクセス指定子に影響される。
class Show { public: static void Value(char ch) {//引数の違う同名関数 オーバーロード cout << ch << endl; } static void Value(const char* str) {//引数の違う同名関数 オーバーロード cout << str << endl; } }; class Show2 :public Show{ public: /* static void Value(char ch) {//Showの同名メンバ関数を上書き オーバーライド int n = static_cast<unsigned char>(ch); cout << n << endl; } */ private: using Show::Value; //usingをprivate }; //静的メンバ関数はクラスのオブジェクトが無くても呼び出せる int main() { Show2::Value('A');//使えなくなった Show::Value("Hoge"); Show2::Value("Hoge");//使えなくなった system("pause"); }
今回は直接呼び出しているため、private になったVlaueが使えなくなった。
private なので内部からは使える。
Show :: Value の using が private
なのはわかる気がするけど、オーバーライドしたのもprivate 扱いになるのか。
usingここまで。