アプリ版:「スタンプのみでお礼する」機能のリリースについて

C++でお聞きしたいことがあります。
初心者ですのでご容赦ください。

//基本クラス
class a1
{
protected:
a1();
};

//派生クラス
class a2 :public a1
{
protected:
a2():a1(){};//継承先以外から作成されたくない
int t;
};

class a3 : public a2 //a2を継承
{
public:
a3();
~a3();
private:
a2*a;//a2のポインタを持つ
};

a3::a3()
{
t = 3;
a = new a2;//コンストラクタの中でnew
}

a3::~a3()
{
delete a;//終わったらdelete
}

int main(void)
{
a3a;

return 0;
}

というソースでa3はa2を継承しています。
ですのでa2のprotectedメンバtにアクセスできるはず。
ここまではいいのですが、
a2のコンストラクタもa3でアクセスでき無いのでしょうか?
a3のコンストラクタでnewしようとすると

error C2248: 'a2::a2' : protected メンバ (クラス 'a2' で宣言されている)にアクセスできません。
a2::a2' の宣言を確認してください。

というエラーが発生します。
やりたいのはa2のような基本クラスが6つほどあり、
a2のメンバ変数が多いので
コンストラクタの引数で指定されたものだけ
コンストラクタないでnewしたいのです。

なぜ、できないのか?
どうすればnewできるようになるのか…。
非常にお手数ですが、
どなたかご回答いただけませんでしょうか?
長文になりましたが、宜しくお願いいたします。

A 回答 (4件)

> しかしa3はa2をpublicで継承しているのに、


> なぜできないのかが疑問なのです。

今の状態でpublic継承に変更してみて、

a3::a3()
{
t = 3;
a = new a2; //コンストラクタの中でnew

の後で、
printf("this→%p, &t→%p, &a→%p, &(a.t)→%p\n",this, &t, a, &(a->t));
などとしてthisとaのアドレスを表示してみると、その時newされたaと自分自身(this)のアドレスが違うのが分かると思います。
自分自身(this)の外側でprotectで宣言されているものにはアクセスできません。
    • good
    • 0
この回答へのお礼

前回回答をいただいたとおり、
friend classにすることにより
解決しました。
ありがとうございました。

お礼日時:2004/11/30 21:14

VC6,VC.NET,GCCで試してみました。


どれもコンパイルできませんでした。

試しにa1に別の関数をprotectedで宣言してa3コンストラクタからアクセスすると問題ないようです。

どうやらコンストラクタのみアクセスできないようですね。
私も知りませんでした。

他の方がprotectedではアクセスできないと書かれていますが、コンストラクタ以外なら全てアクセスできます。(なので、他の方は質問の意味を誤解されてるのではないでしょうか?)
なぜコンストラクタだけアクセスできないのでしょう?
理由を考えてみましたが思い当たりませんでした。

MSのみでなくGCCもそうなので、おそらく仕様なのでしょう。
残念です。

解決策としては、friend a3をa2で宣言するしかないようですね。
    • good
    • 0
この回答へのお礼

newせずに普通にメンバとしてインスタンスを持たせることは
できますので、
#1様が仰っていたとおりなのでしょうね?…。

解決策をご教授していただいてありがとうございました。
friendすることにより
解決いたしました。

お礼日時:2004/11/30 21:16

a3::a3()の中で


a2のインスタンスを作成してどないすんの。
何か勘違いしていませんか?
コンパイルエラーの意味は、

int main(void)
{
a2 *a = new a2;
}

というのが出来ないのと同じ理由ですよ。
派生クラスa3で親クラスのa2のメンバ変数tに
アクセスしたいだけならその一文はいらないです。

a3::a3()
{
t = 3;
}

この回答への補足

質問がわかりづらくて申し訳ありません。

main の中で a2 のインスタンスが
作成できない理由はわかります。
a2のコンストラクタがprotectedですから…。
しかしa3はa2をpublicで継承しているのに、
なぜできないのかが疑問なのです。
別段、t3にアクセスしたいために
a2のインスタンスを作成したいわけではないのです。

補足日時:2004/11/30 18:20
    • good
    • 0

> なぜ、できないのか?



a2::a2()はprotectedですので、これを継承したクラスのオブジェクト、インスタンスの中で使えます。

a3::a3()
{
t = 3;
a = new a2; //コンストラクタの中でnew
}

の処理ですと、aに代入されるa2クラスのインスタンスのアドレスは、a3=a2のアドレスと異なるものです。
アドレスが異なる→置き場所が異なりますから、これは別のオブジェクトという事になりますので、自分自身の中身で無いのでアクセスできないという事になります。

--
> どうすればnewできるようになるのか…。

しばらくコーディングから遠ざかっていたので、適切なクラスの構成が思いつきません。
friendを使うのかな?(自信なし)
    • good
    • 0
この回答へのお礼

う~んと…
かなり難しいです。
意味はわかりませんが、
friend関数を使うとよろしいのでしょうか?
さっそく調べてみます。
回答ありがとうございました。

お礼日時:2004/11/30 18:20

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A