简体   繁体   中英

Why can't I define a object of class(which inherited another class) outside the main function?

I am currently working with VS15 using the fltk library. When I try to create an object of my class (which inherits Fl_Double_Window) outside the main function the program crashed.

#include"FL/Fl.H"
#include"FL/Fl_Double_Window.h"
#include"FL/Fl_draw.h"
#include"FL/Fl_Slider.H"
#include"FL/Fl_Input.H"
#include"FL/Fl_Button.H"
#include"FL/Fl_Text_Display.H"
#include<string>

struct MyWindow :Fl_Double_Window {
    MyWindow(string s):Fl_Double_Window(10, 10, 500, 500, s.c_str()){
        color(FL_BLACK);
        show();
    }
};

MyWindow window("Special");

int main()
{
    return Fl::run();
}

However, everything works properly when I create an object of class Fl_Double_Window directly (again outside the main function):

#include"FL/Fl.H"
#include"FL/Fl_Double_Window.h"
#include"FL/Fl_draw.h"
#include"FL/Fl_Slider.H"
#include"FL/Fl_Input.H"
#include"FL/Fl_Button.H"
#include"FL/Fl_Text_Display.H"
#include<string>

string name = "Special";
Fl_Double_Window window(10, 10, 500, 500, name.c_str());

int main()
{
    window.color(FL_BLACK);
    window.show();
    return Fl::run();
}

The guy I downloaded the code from run the code on Ubuntu using C++11, and the program works in both cases. I'm confused and I really can't figure out what the problem is.

You are getting a crash because you've put show (as mentioned by @bruno) in the constructor. If you take show out of the constructor and put it in main, you won't get the crash that you are seeing but the title will be incorrect for the reasons that @Sam Varshavchik has mentioned.

struct MyWindow :Fl_Double_Window {
    MyWindow(const std::string& s)
   :    Fl_Double_Window(10, 10, 500, 500) // 1) Do not set the title here
    ,   caption(s)  // 2) Take a copy of the title
    {
        // 3) Set the title here
        this->copy_label(caption.c_str());
        color(FL_BLACK);
        // 4) Remove show from constructor
        // show();
    }

    // 5) Declare caption - see Sam's solution
    std::string caption;
};

MyWindow window("Special");


int main()
{
    // 6) Move show here
    window.show();
    return Fl::run();
}
MyWindow(string s)

A constructor is not much different from a function. s is a parameter to the constructor. Once the constructor returns, s gets destroyed.

                  :Fl_Double_Window(10, 10, 500, 500, s.c_str()){

c_str() returns a pointer to s 's contents, and passes it to the superclass's constructor. However because s will get destroyed, any further usage of that pointer becomes undefined behavior, and a likely crash. Which is what's obviously happening.

The solution is slightly complicated. This requires a delicate juggling act if you still wish to inherit from FL_Double_Window :

struct my_data {
    string s_name;
    my_data(string s) : s_name(s)
    {
    }
};

struct MyWindow :my_data, Fl_Double_Window {

    MyWindow(string s): my_data(s),
                        Fl_Double_Window(10, 10, 500, 500, this->s_name.c_str()){
        color(FL_BLACK);
        show();
    }
};

This juggles the order in which things get constructed and destroyed so that the s_name class member continues to exist as long as FL_DoubleWindow exists.

There's also the (much) easier option of passing in a reference, but then you will have to ensure that the referenced std::string exists as long as the window object exists. This approach, although slightly cumbersome, is also more bulletproof.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM