wxWidgets   気になる事

ホーム   C/C++チュートリアル


wxWidgetsで、あまり説明されていない、気になる事を、 書いてみようと思います。

IMPLEMENT_APPとOnInit()

IMPLEMENT_APP と OnInit( ) が、実際どのような実装になっているのか試してみようと思います。

implement.cpp


#include <wx/wx.h>

class App : public wxApp
{
public:
    bool OnInit()
    {
        std::cout << "Hello" << std::endl;
        return true;
    }
};

IMPLEMENT_APP(App)
    

このコードをコンパイルして、端末(ターミナル)で実行すると次のようになります。


Hello

    

「Hello」と表示された後に、アプリケーションが終了していないことが分かります。OnInit( ) は、true; 返すと、アプリケーションは起動し続けます。^C(Control + C)で終了させてください。
OnInit( )の中の return true; を return false; と変更すると、次のようにアプリケーションが自動的に終了します。


Hello
$
    

IMPLEMENT_APP(App)をIMPLEMENT_APP(wxAPP)と変更して、引数にスーパークラスを与えると、アプリケーションは何もせず起動し続けます。



    

wxApp の OnInit( ) は仮想関数として定義されていますが、return true; 以外は 何も実装されていないことが分かります。


ウィンドウも表示させてみます。

implement.cpp


#include <wx/wx.h>

class App : public wxApp
{
public:
    bool OnInit()
    {
        std::cout << "Hello" << std::endl;
        //Exit();
        (new wxFrame(NULL, -1, "Hello"))->Show();
        return true;
    }
};

IMPLEMENT_APP(App)
	  

ウィンドウも無事に表示されます。
return true; を return false; に変えると、「Hello」とだけ表示されてアプリケーションが終了します。おそらくウィンドウは一瞬だけ表示されて終了しているので、見えないだけだろうと思います。 ⁄ ⁄ Exit(); のコメントを外して、Exit(); とすると、その時点でアプリケーションが終了されます。


次に、IMPLEMENT_APP の部分を、main( ) 関数で書いてみます。

implement.cpp


#include <wx/wx.h>

class App : public wxApp
{
public:
    bool OnInit()
    {
        std::cout << "Hello" << std::endl;
        return true;
    }
};

int main()
{
    wxApp *app = new App();
    app->OnInit();
    
    return 0;
}
	
  1. 実行結果は、「Hello」と表示されて終了します。return true; は有効にならないみたいです。
  2. ここではわざとスーパークラスの wxApp 型のポインターに、App のインスタンスを代入しています。無事に、サブクラス App の OnInit( ) が呼び出されいることから、OnInit( ) が仮想関数であることがここでも分かります。
  3. 公開されているサンプルコードでは、wxApp のサブクラスで OnInit( ) 関数を再定義(オーバーライド)する際に、virtual キーワードをつけています。本来、仮想関数を再定義(オーバーライド)する際には、virtual キーワードはつける必要はありません。わざわざ virtual をつけているのは、「再定義(オーバーライド)しなさいと何も実行されませんよ」という注意喚起だと思います。


main( ) 関数から OnInit( ) を呼び出した場合は、ウィンドウは表示できません。

implement.cpp


#include <wx/wx.h>

class App : public wxApp
{
public:
    bool OnInit()
    {
        std::cout << "Hello" << std::endl;
        (new wxFrame(NULL, -1, "Hello"))->Show();
        return true;
    }
};

int main()
{
    wxApp *app = new App();
    app->OnInit();
    
    return 0;
}
    

このコードはコンパイルはできますが、実行結果は、プラットフォームによって違います。Linux では実行時エラーになりますが、macOS では次のように表示されます。


Hello
Segmentation fault: 11
	

どちらにしても、main() 関数からの呼び出しでは、 ウィンドウは表示できないみたいです。

メモリー管理

次のコードをコンパイルして、ターミナルで実行してみてください。

memory.cpp


#include <wx/wx.h>

class Hello : public wxFrame
{
public:
	Hello();
	~Hello();
};

class App : public wxApp
{
public:
	virtual bool OnInit();
};

Hello::Hello() : wxFrame(NULL, -1, wxT("Hello wxWidgets!"))
{ std::cout << "Created" << std::endl; }
Hello::~Hello()
{ std::cout << "Deleted" << std::endl; }

IMPLEMENT_APP(App)

bool App::OnInit()
{
	Hello *hello = new Hello();
	hello->Show();
	
	return true;
}
    

実行結果


// 起動すると次のように表示されます。
Created
// 終了すると次のように表示されます。
Deleted
    

OnInit( ) の中で、hello ポインターを delete する記述はしていません。しかし、 Hello クラスのインスタンスは、アプリケーション終了時に 無事に、破棄(メモリー解放)されるみたいです。
OnInit( ) 内のポインターは自動的に delete されると思ってもいいみたいです。

ConnectとBind

wxWidgets 2.x では、Connect しか使えません。
wxWidgets 3.x では、Connect と Bind の両方が使えます。

wxT

wxWidgets 2.x では、クラス内で用いるすべての文字列で wxT を使わなければなりません。
wxWidgets 3.x では、クラス内で用いる日本語などの2バイト文字列には wxT を使わなければなりませんが、英語などの1バイト文字列には wxT を使う必要はありません。
macOS の wxWidgets 3.x では、日本語も英語も wxT を使う必要はありません。


41727 visits
Posted: Dec. 09, 2019
Update: Dec. 10, 2019

ホーム   C/C++チュートリアル   目次