継承されていないクラスのコンストラクターの呼び出し方(初学者)

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
keito94
記事: 264
登録日時: 3年前
連絡を取る:

継承されていないクラスのコンストラクターの呼び出し方(初学者)

#1

投稿記事 by keito94 » 3年前

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();
}
想定される結果はのは以下のとおりです。

コード:

コンストラクター起動!
違うクラスのコンストラクター。
第三のコンストラクター。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

Iseuma14
記事: 54
登録日時: 5年前

Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)

#2

投稿記事 by Iseuma14 » 3年前

あなたのプログラムをそのままコピーしてVSに貼るとクラスAのConstの定義のところにカッコが付いていなかったり、aのヘッダのConstにセミコロンが付いていなかったり、Aのメンバでないbをnewしていたりと多くのエラーが排出され、実行ができませんでした。

これはあなたの実行環境にあるコードと同じものですか?
実行環境と同じコードをコピーペーストして貼ることをおすすめいたします。

アバター
purin52002
記事: 235
登録日時: 3年前
連絡を取る:

Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)

#3

投稿記事 by purin52002 » 3年前

こんばんは、今日の晩御飯は焼きそばです。

今回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
例えるなら、ナポリタンを焼きそばと言い張るような、、、
すみません、黙ります^^;
最後に編集したユーザー purin52002 on 2017年4月28日(金) 22:52 [ 編集 2 回目 ]
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
みけCAT
記事: 6311
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)

#4

投稿記事 by みけCAT » 3年前

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というエラーは出たものの、「左辺値ウンタラカンタラ」のようなエラーは再現できませんでした。
このエラーの解決法を聞きたければ、最小限の・自己完結した・確認可能なサンプルコードを提示してください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
keito94
記事: 264
登録日時: 3年前
連絡を取る:

Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)

#5

投稿記事 by keito94 » 3年前

みけCAT さんが書きました: このエラーの解決法を聞きたければ、最小限の・自己完結した・確認可能なサンプルコードを提示してください。
こういうことでしょうか?

コード:

#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;
}
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
みけCAT
記事: 6311
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)

#6

投稿記事 by みけCAT » 3年前

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();//ここで何らかのエラーが発生する。
  ~~~~~^~~~~~~~~
という警告が出ました。

「左辺値ウンタラカンタラ」というエラーの原文をそのまま(ユーザー名などの個人情報は隠して)貼っていただけますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
keito94
記事: 264
登録日時: 3年前
連絡を取る:

Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)

#7

投稿記事 by keito94 » 3年前

左辺値ウンタラカンタラは気のせいだったようです。訂正してください。
…でも、この例外の原因ならわかりますよね?
添付ファイル
質問.PNG
質問.PNG (5.38 KiB) 閲覧数: 1997 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
keito94
記事: 264
登録日時: 3年前
連絡を取る:

Re: 継承されていないクラスのコンストラクターの呼び出し方(初学者)

#8

投稿記事 by keito94 » 3年前

ごめんなさい、質問の意味が僕にしかわかりませんでしたね…。知識不足がまたたたってしまいました。
しっかり、C言語とC++の勉強をし直してこようと思います。
一応この質問は解決とさせてください。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

返信

“C言語何でも質問掲示板” へ戻る