ページ 1 / 1
継承されていないクラスのコンストラクターの呼び出し方(初学者)
Posted: 2017年4月28日(金) 19:47
by keito94
C++の初歩的な質問すいません。以下のようなソースコードは継承されていないクラスから違うクラスで宣言されているクラスのコンストラクターを呼び出そうとしているものです。検索しても継承されているコンストラクターの情報しかありませんでした。コメントのようなエラーが出てしまいます。
A.cpp
コード:
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
void A::Const{
cout << "コンストラクター起動!" << endl;
b = new B();
delete b;
}
int main(void){
A* a;
a.Const
return 0;
}
A.h
コード:
#pragma once
#include "C.h"
class A{
public:
C* c;
void Const()
};
B.h
コード:
#pragma once
class A
class C
class B{
public:
A* a;
B();
};
B.cpp
コード:
#include <iostream>
#include "C.h"
#include "B.h"
#include "A.h"
using namespace std;
B::B(){
cout << "違うクラスのコンストラクター" << endl;
a->c = new C();//ここで左辺値ウンタラカンタラが出る。
}
C.cpp
コード:
#include <iostream>
#include "C.h"
using namespace std;
C::C(){
cout << "第三のコンストラクター。" << endl;
}
C.h
コード:
#pragma once
class C{
C();
}
想定される結果はのは以下のとおりです。
コード:
コンストラクター起動!
違うクラスのコンストラクター。
第三のコンストラクター。
Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)
Posted: 2017年4月28日(金) 20:33
by Iseuma14
あなたのプログラムをそのままコピーしてVSに貼るとクラスAのConstの定義のところにカッコが付いていなかったり、aのヘッダのConstにセミコロンが付いていなかったり、Aのメンバでないbをnewしていたりと多くのエラーが排出され、実行ができませんでした。
これはあなたの実行環境にあるコードと同じものですか?
実行環境と同じコードをコピーペーストして貼ることをおすすめいたします。
Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)
Posted: 2017年4月28日(金) 20:42
by purin52002
こんばんは、今日の晩御飯は焼きそばです。
今回keitoさんがやっているのは
「今日はパンがたべたいな」「じゃあ焼きそばにするね^^」
のようなことです。
ごめんなさい、焼きそばがうれしくて調子に乗りました^^;
コード:
class A;//中身は省略
class B;
class C : public A;
class MyClass
{
public:
A* a;
A* b;
A* c;
};
int main()
{
MyClass obj;
obj->a=new A();//ok
obj->b=new B();//error
obj->c=new C();//ok!
}
簡単に説明すると、
ポインタに違う型のポインタを代入しようとするからエラーになります。
(int*にchar*入れちゃダメ!みたいなイメージ)
詳しく説明すると
クラスの継承にはポインタを使います。
なぜポインタを使うのでしょうか?
それはポインタのメモリサイズが同じだからです。
じゃあ違う型のポインタ入れてもいいじゃん!
ダメなんです^p^詳しい理由は知りません^p^
じゃあなんで基底クラスのポインタに継承クラスのポインタを入れてもいいんですか?
基底クラスでできることは継承クラスでもできますよね?
じゃあ基底クラスの機能だけ使うっていうんなら特別に許してやろう^^
って感じで継承クラスのポインタを入れられるわけです。
正しい知識はググってください^^;
[hr]
まとめ
・ポインタに違う型のポインタを入れたらエラー
・基底クラスのポインタに継承クラスのポインタを入れるのはok!
・そのポインタでできることは基底クラスでできることのみ。
[hr]
訂正とお詫び
質問を読み直してみたところ、私の指摘がトンデモなことに気づきましたorz
例えるなら、ナポリタンを焼きそばと言い張るような、、、
すみません、黙ります^^;
Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)
Posted: 2017年4月28日(金) 22:20
by みけCAT
No: 1のコードを適当に1個のソースコードにまとめ、コンパイルが通るようにしてみました。
コード:
#include <iostream>
class C{
public: /* Cのコンストラクタがprivateだったので、publicに変更 */
C();
}; /* ;を追加 */
class A{
public:
C* c;
void Const(); /* ;を追加 */
};
class B{
public:
A* a;
B();
};
using namespace std;
void A::Const(){ /* ()を追加 */
B* b; /* bの定義を追加 */
cout << "コンストラクター起動!" << endl;
b = new B();
delete b;
}
int main(void){
A a; /* *を取る */
a.Const(); /* ();を追加 */
return 0;
}
B::B(){
cout << "違うクラスのコンストラクター" << endl;
a->c = new C();//ここで左辺値ウンタラカンタラが出る。
}
C::C(){
cout << "第三のコンストラクター。" << endl;
}
keito94 さんが書きました:ここで左辺値ウンタラカンタラが出る。
という場所ではCのコンストラクタがprivateというエラーは出たものの、「左辺値ウンタラカンタラ」のようなエラーは再現できませんでした。
このエラーの解決法を聞きたければ、
最小限の・自己完結した・確認可能なサンプルコードを提示してください。
Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)
Posted: 2017年4月29日(土) 13:14
by keito94
こういうことでしょうか?
コード:
#include <iostream>
using namespace std;
class B {
public:
B();
};
class A {
public:
B* b;
};
B::B() {
cout << "Bのコンストラクターが起動されました。" << endl;
}
int main(void) {
A* a;
cout << "Bのクラスのコンストラクターを起動します。" << endl;
a->b = new B();//ここで何らかのエラーが発生する。
return 0;
}
Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)
Posted: 2017年4月29日(土) 14:02
by みけCAT
keito94 さんが書きました:こういうことでしょうか?
違うと思います。
このコードはコンパイルが通り、明示的に初期化されていないポインタaをデリファレンスしたことによりSegmentation Faultが発生しましたが、
「左辺値ウンタラカンタラ」に該当しそうなエラーは得られませんでした。
また、
コード:
prog.cc: In function 'int main()':
prog.cc:21:7: warning: 'a' may be used uninitialized in this function [-Wmaybe-uninitialized]
a->b = new B();//ここで何らかのエラーが発生する。
~~~~~^~~~~~~~~
という警告が出ました。
「左辺値ウンタラカンタラ」というエラーの原文をそのまま(ユーザー名などの個人情報は隠して)貼っていただけますか?
Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)
Posted: 2017年4月29日(土) 14:25
by keito94
左辺値ウンタラカンタラは気のせいだったようです。訂正してください。
…でも、この例外の原因ならわかりますよね?
Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)
Posted: 2017年4月29日(土) 15:37
by keito94
ごめんなさい、質問の意味が僕にしかわかりませんでしたね…。知識不足がまたたたってしまいました。
しっかり、C言語とC++の勉強をし直してこようと思います。
一応この質問は解決とさせてください。