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

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

新規登録して質問してみよう
ただいま回答率
85.49%
C++

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

Q&A

解決済

2回答

2719閲覧

MainWindowクラスから他のクラスの呼出方法

nqf27650

総合スコア115

C++

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

0グッド

0クリップ

投稿2016/12/25 04:24

Qt5.5.1、QtCreator3.5.1でウィジェットAppを作成しています。

MainWindowクラスからPrinterクラスのprintルーチンを呼び出す場合に
ポインタを介しての呼び出しの場合は、突然プログラムを終了します。
尚、添付コードのMainWindowクラスの該当箇所を参照ください

Q1)この突然プログラムを終了する件について、コメント頂け
ますと大変ありがたいです。

添付コード
printer.h================
#ifndef PRINTER_H
#define PRINTER_H
#include <QObject> //for QString str;
class Printer
{
public:
Printer();
void print();
QString str;
};
#endif // PRINTER_H

printer.cpp================
#include "printer.h"
#include <QObject> //for qPrintable
Printer *obj;
Printer::Printer()
{
str="OK";
obj=this;
qDebug("constructor");
}
void Printer::print(){
qDebug("%s", qPrintable(str));
}

mainwindow.h================
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp================
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "printer.h"

extern Printer *obj;

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
Printer p; //正常に動作する
p.print(); //正常に動作する

//Printer *pp; //Form画面の表示がなく、突然終了
//pp->print();

//obj->print(); //Form画面の表示がなく、突然終了
}

MainWindow::~MainWindow()
{
delete ui;
}

以上

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

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

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

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

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

guest

回答2

0

ベストアンサー

こんにちは。

Printer p; //正常に動作する
obj->print(); //Form画面の表示がなく、突然終了

この2つを有効にしておけば、前者でPrinterのコンストラクタが呼び出されて、グローバル変数objにPrinterオブジェクトが設定されるので動作はすると思います。

しかし、Printerオブジェクトが複数生成されるような場合、objに設定されているものは最後にコンストラクトされたものですし、その最後のものがデストラクトされるとobjが指すオブジェクトは不正(既に破棄)になります。
たいへんバギーな設計です。

例えば、Printerオブジェクトを複数生成する必要がないのでしたら、シングルトン化すると対策できると思います。
複数必要でしたら、Printerオブジェクトの管理方法をきちんと設計(どうやって管理し、いつ誰が生成/破棄するのかなどなど)しましょう。

投稿2016/12/25 04:38

編集2016/12/25 04:40
Chironian

総合スコア23272

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

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

nqf27650

2016/12/25 05:23

//================= Printer p; obj->print(); 前者でPrinterのコンストラクタが呼び出されて、グローバル変数objにPrinterオブジェクトが設定されるので動作はすると思います。 <---了解しました。感謝 下記の場合は、pにはポインターが入りますか? また、pの後処理も必要ですか? ご説明頂けますと、大変助かります。 Printer p; //正常に動作する p.print();
Chironian

2016/12/25 07:36

> 下記の場合は、pにはポインターが入りますか? この場合、pはオブジェクトそのものです。ポインタではありません。 {から}の間で定義された変数はその}までが有効範囲です。 その有効範囲から出る時に自動的に解放されます。(デストラクタが呼ばれ、記憶領域が解放される)
guest

0

ポインタ変数の宣言のみで実体がないからです。

C++

1pp = new Printer();

のように実体を生成する必要があります。

objのほうはChironianさんも指摘のとおり、動作はすると思います。
以下の類似ソースでは正常に動作します。

C++

1#include <iostream> 2using namespace std; 3 4class Printer; 5Printer *obj = NULL; 6 7class Printer{ 8public: 9 Printer(){ 10 obj = this; 11 } 12 void Print( string s){ 13 cout << s << endl; 14 } 15}; 16 17class Wnd{ 18public: 19 Wnd(){ 20 Printer p; 21 p.Print("p"); 22 obj->Print("obj"); 23 } 24}; 25 26int main() { 27 Wnd w; 28 // "p" 29 // "obj" 30 return 0; 31}

投稿2016/12/25 04:36

編集2016/12/25 05:04
can110

総合スコア38256

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

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

nqf27650

2016/12/25 05:28

> class Printer; Printer *obj = NULL; <ーーこの場合、print()を呼び出す場合の書き方は? お手数ですが、宜しくお願いします。
can110

2016/12/25 08:29

提示したソースではWndクラスのコンストラクタ内で呼び出していますが、質問は別の場所でも呼び出したいという意味でしょうか? この例ではobjの指す実体pのスコープ(寿命)はコンストラクタ内に限るので、ほかの場所では呼び出してはいけません。 (クラス)変数のスコープやポインタ、コンストラクタ、デストラクタなどについて基礎的な教科書やWebページで再確認してみてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問