質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

13365閲覧

C++派生クラスのメンバ変数にアクセスする方法

itin

総合スコア15

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1グッド

0クリップ

投稿2018/10/21 13:28

C++にてポリモーフィズムで派生クラスのメンバ変数にアクセスしたいのですが,どのように書けばそうできるのかわかりません。
ご教授お願いします。

詳細

C++

1struct Base { 2 int a; 3}; 4 5struct A : public Base { 6 int b; 7}; 8 9struct B : public Base { 10 int c; 11};

などのコードでstd::vector<Base*>などを使いBaseから派生した複数,多種類のstructをまとめ管理したいです。
しかし, メンバ変数にアクセスできないという問題が発生しました。
この問題を解決するようなコード,またはこう設計すべしというものがあったら教えてください。

ソースコード

C++

1#include <iostream> 2 3struct Base { 4 int a; 5}; 6 7struct A : public Base { 8 int a; 9 int b; 10}; 11 12int main() { 13 Base *ptr; 14 A hoge; 15 hoge.a = 2; 16 hoge.b = 3; 17 ptr = &hoge; 18 19 std::cout << "ptr->a:" << ptr->a << std::endl; // 2が出ない 20 std::cout << "ptr->b:" << ptr->b << std::endl; // Error 21 return 0; 22}

上記のコードでptr->a, ptr->bを表示できるようにしたい

nishiys👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

c++

1struct A : public Base { 2 int b; 3};

ならば、aについては期待通りの動作をすると思います。
また、polymorphicな扱いをするならばデストラクタについて考えるべきです。

派生クラスを基底クラスとしてdeleteすると基底クラスのデストラクタのみが呼ばれるので
virtualなデストラクタを宣言する事が必要です。

また、virtualな関数を定義する事でdynamic_castが使用可能になるので

c++

1#include <iostream> 2 3struct Base { 4 int a; 5 virtual ~Base() = default; 6}; 7 8struct A : public Base { 9 int b; 10}; 11 12int main() { 13 Base *ptr; 14 A hoge; 15 hoge.a = 2; 16 hoge.b = 3; 17 ptr = &hoge; 18 19 std::cout << "ptr->a:" << ptr->a << std::endl; 20 if(A* a_ptr = dynamic_cast<A*>(ptr)) 21 std::cout << "ptr->b:" << a_ptr->b << std::endl; 22 return 0; 23}

あたりが妥当ではないでしょうか


ただし、わざわざ基底クラスのポインタから派生クラスの変数に対してアクセスする事は
設計上の間違いと言わざるをえないでしょう。
仮想メンバ関数などを用いることで派生クラスに任せた方が分かりやすくなることでしょう。

投稿2018/10/21 18:06

編集2018/10/21 18:20
asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ポリモーフィズムで派生クラスのメンバ変数にアクセスしたいのですが

基底クラスのポインタや参照経由でポリモーフィックにアクセスできるのは、基底クラスにあるメンバだけです。派生クラスにしかないメンバにアクセスしたいのであれば、そのクラスのポインタにキャストしてからアクセスする必要があります。

投稿2018/10/21 13:38

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

そもそもやろうとしていることが、「ポリモーフィズム」の範疇ではないです。
ポリモーフィズムは、同じ記述で異なる振舞いを行うことです。(例えば、ptr->foo()の振る舞いがAとBで異なる等)
逆に、異なる記述で異なる振舞いをするのは普通のことです。そこにポリモーフィズムでよく使われる考え方は本質的に役に立ちません。(同じ名前の仮想関数でオーバーライドするなど。)

このようなケースでは、ダウンキャストすることも少なくないです。
dynamic_castを使えば安全・お手軽にダウンキャストできます。なお、仮想関数の定義を忘れないことが大事です。デストラクタを仮想関数にすると安全確実です。(基底クラスへのポインタをdeleteする場合には事実上必須ですし。)

意外にdynamic_castは遅いので、高速化が必要な時は、基底クラスに「派生クラスの型」を記録する変数を用意し、コンストラクト時にそれを設定しダウンキャスト時に確認してstatic_castするメジャーなOSS(clang)もあります。


【余談ですが】
dynamic_cast、もしくは、ダウンキャストを使うのは「設計がおかしいので設計をみなおすべき」というルールを書いている人も少なくないです。ポリモーフィックに使うのが好ましいケースでダウンキャストしていた場合はまさにその通りと思います。(そのような不適切な設計も少なくないだろうと思います。)
しかし、本質的に異なるものを同じ記述でアクセスするのはおかしいですから、そのような時にダウンキャストするのは適切です。

投稿2018/10/22 03:50

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問