継承は全てpublicとします。
基本クラスのポインタに派生クラスのポインタを代入できますが、
基本クラスのポインタの配列(vectorでもOK)を引数とする関数に
派生クラスのポインタの配列を渡したいのですがどうしたらよいのでしょうか?
class A{
};
class B : public A{
};
void f(A *ppA[])
{
}
int main()
{
B *pB[10];
f(pB); // <-これがエラー
return 0;
}
環境はWinXP + VC6です。
MFCは使ってません。(って見りゃわかりますね。)
直接渡すことは出来ません。(少なくとも保障されません)
事前に変換する必要があります。
REE さんの回答で完璧なのですが補足など。
pB は &pB[0] つまり B** 型です。 ppA は A** 型です。
B** から A** へ暗黙に型変換するコンテキストは無いわけです。
(B* から A* へ暗黙に型変換するコンテキストはあるが、上記の変換は無い)
この場合、渡したいのは配列の中身の B* が A* になって欲しい、のでしょう。
ということは配列の中身を1つづつ変換しなければなりません。
似てるけど違うバグ(もっとエグイ:コンパイルエラーにならない)を、
ウチの pc-lint は検出するぜい!と gimpel 社が CM してるページなどを
紹介してみたりして。
http://www.gimpel.com/html/oldbugs/bug1552.htm
http://www.gimpel.com/html/bugs.htm
回答を見ずに全部正解できたらなかなかのものです。
おふたりともありがとうございます。
さらに質問したいのですが、B**をA**に強引にキャストしてはいけないのでしょうか?
例えば上の例だと
f((A **)pB);
とすればコンパイルは可能です。
ポインタは全て同じサイズだと思いますのでこれでもOKな気がするのですが。
vector<B *>をvector<A *>にしたい場合はお答え通りに変換したvectorを作ればいい
ようですね。
なぜ駄目かと言うと、B* から A* への変換で、指す先が変わることがありえるのです。
ポインタのサイズが同じで、単一継承しかしていなければ、大丈夫かもしれません。
しかし、少なくとも保障されていません。
ありがとうございます。
> なぜ駄目かと言うと、B* から A* への変換で、指す先が変わることがありえるのす。
なるほど、確かに多重継承した場合なんかそうですね。
保障されていないというのもうなずけます。
安全性を考えると上の例のような強引なキャストは避けたほうがいいですね。