新規記事の投稿を行うことで、非表示にすることが可能です。
2017年12月15日
《その179》 using宣言によるアクセス権の調整 & p.174演習4-3
using宣言によるアクセス権の調整
次のプログラムで、基底クラス Base は、
private:
int型の a
public:
コンストラクタ Base
関数 func1
で構成されています。
また、基底クラス Base から private派生によって作られる派生クラス Derived は、実装された基底クラスのメンバに加えて、
private:
int型の b
public:
コンストラクタ Derived
関数 func2
で構成されています。
private派生であるため、基底クラス Base では公開メンバであった 関数 func1 は、派生クラス Derived においては、基本的には外部から呼び出すことができません。
この func1 のアクセス権を using宣言により調整することができます。アクセス権を調整することによって、派生クラス Derived の外部から、関数 func1 を呼び出せるようにできるのです。
下の ★1. の箇所が using宣言です。★2. の箇所で、アクセス権を調整して使えるようになった func1 を利用しています。
// ------------------------------------
#include <iostream>
class Base {
int a;
public:
Base(int aa) : a(aa) { }
void func1() const {
std::cout << "a = " << a << '\n';
}
};
class Derived : private Base {
int b;
public:
Derived(int aa, int bb) : Base(aa), b(bb) { }
void func2() const {
std::cout << "b = " << b << '\n';
}
using Base::func1; // ★1.
};
int main()
{
Derived drvd(11, 22);
drvd.func1(); // ★2.
drvd.func2();
}
// ------------------------------------
![f04_0009.png](/cplusplus/file/f04_0009.png)
新版明解C++中級編 p.174 演習4-3
次のクラス Base型と Derived型に対して、アップキャストとダウンキャストを試みるプログラムを作成せよ。
// ------------------------------------
class Base {
int a;
int b;
public:
Base(int aa, int bb) : a(aa), b(bb) { }
void func() const {
std::cout << "a = " << a << '\n';
std::cout << "b = " << b << '\n';
}
};
class Derived : public Base {
int x;
public:
Derived(int aa, int bb, int xx) : Base(aa, bb), x(xx) { }
void method() const {
func();
std::cout << "x = " << x << '\n';
}
};
// ------------------------------------
◆以下が解答のプログラムです。
// p174_演習4-3
#include <iostream>
class Base {
int a;
int b;
public:
Base(int aa, int bb) : a(aa), b(bb) { }
void func() const {
std::cout << "a = " << a << '\n';
std::cout << "b = " << b << '\n';
}
};
class Derived : public Base {
int x;
public:
Derived(int aa, int bb, int xx) : Base(aa, bb), x(xx) { }
void method() const {
func();
std::cout << "x = " << x << '\n';
}
};
int main()
{
Base base(10, 20);
Derived drvd(11, 22, 33);
// ◆ ------------------▽
Base* ptr_b1 = &base;
ptr_b1->func(); // a = 10
// b = 20
// ptr_b1->method(); /* エラー */
// ---------------------△
// ◆ アップキャスト----▽
Base* ptr_b2 = &drvd;
ptr_b2->func(); // a = 11
// b = 22
// ptr_b2->method(); /* エラー */
// ---------------------△
// ◆ ダウンキャスト----▽
// Derived* ptr_d1 = &base; /* エラー */
// ---------------------△
// ◆ ------------------▽
Derived* ptr_d2 = &drvd;
ptr_d2->func(); // a = 11
// b = 22
ptr_d2->method(); // a = 11
// b = 22
// x = 33
}
// ---------------------△
《その178》 クラスのメンバーへのアクセス
クラスのメンバーが、例えば、次の a, b, c である場合、
private:
int a;
protected:
int b;
public:
int c;
a には、定義されたクラスの メンバー関数,フレンド関数からアクセスできます。
b には、定義されたクラスやその派生クラスの メンバー関数,フレンド関数からアクセスできます。
c には、どこからでもアクセスできます。
さらに、このクラスからの private派生,protected派生,public派生 による派生クラスの場合には、a, b, c へのアクセス可否がどのようになるのか、一応、確認してみました。
// ------------------------------------
using namespace std;
/* 基底クラス(親クラス) */
class Class00 {
private:
int a;
protected:
int b;
public:
int c;
Class00() : a(10), b(20), c(30) { }
void get_a() { cout << a << '\n'; }
void get_b() { cout << b << '\n'; }
void get_c() { cout << c << '\n'; }
};
// ------------------
/* private派生(子クラス) */
class Class11 : private Class00 {
public:
// void get_a() { cout << a << '\n'; } // エラー
void get_b() { cout << b << '\n'; }
void get_c() { cout << c << '\n'; }
};
/* private派生(孫クラス) */
class Class12 : private Class11 {
public:
// void get_a() { cout << a << '\n'; } // エラー
// void get_b() { cout << b << '\n'; } // エラー
// void get_c() { cout << c << '\n'; } // エラー
};
// ------------------
/* protected派生(子クラス) */
class Class21 : protected Class00 {
public:
// void get_a() { cout << a << '\n'; } // エラー
void get_b() { cout << b << '\n'; }
void get_c() { cout << c << '\n'; }
};
/* protected派生(孫クラス) */
class Class22 : protected Class21 {
public:
// void get_a() { cout << a << '\n'; } // エラー
void get_b() { cout << b << '\n'; }
void get_c() { cout << c << '\n'; }
};
// ------------------
/* public派生(子クラス) */
class Class31 : public Class00 {
public:
// void get_a() { cout << a << '\n'; } // エラー
void get_b() { cout << b << '\n'; }
void get_c() { cout << c << '\n'; }
// ゲッタ get_a(), get_b(), get_c()は public の
// ままで継承されているので記述不要。
};
/* public派生(孫クラス) */
class Class32 : public Class31 {
public:
// void get_a() { cout << a << '\n'; } // エラー
void get_b() { cout << b << '\n'; }
void get_c() { cout << c << '\n'; }
// ゲッタ get_a(), get_b(), get_c()は public の
// ままで継承されているので記述不要。
};
int main() {
Class00 c00;
// cout << c00.a << '\n'; // エラー
// cout << c00.b << '\n'; // エラー
cout << c00.c << '\n'; // 30
Class11 c11;
// cout << c11.a << '\n'; // エラー
// cout << c11.b << '\n'; // エラー
// cout << c11.c << '\n'; // エラー
Class21 c21;
// cout << c21.a << '\n'; // エラー
// cout << c21.b << '\n'; // エラー
// cout << c21.c << '\n'; // エラー
Class31 c31;
// cout << c31.a << '\n'; // エラー
// cout << c31.b << '\n'; // エラー
cout << c31.c << '\n'; // 30
Class12 c12;
Class22 c22;
Class32 c32;
c00.get_a(); // 10
c00.get_b(); // 20
c00.get_c(); // 30
c11.get_b(); // 20
c11.get_c(); // 30
c21.get_b(); // 20
c21.get_c(); // 30
c22.get_b(); // 20
c22.get_c(); // 30
c31.get_b(); // 20
c31.get_c(); // 30
c32.get_b(); // 20
c32.get_c(); // 30
}