c ++析构函数

时间:2012-07-31 05:27:29

标签: c++ oop constructor destructor static-members

考虑这种情况: 我需要为某些设置创建一个ui。因为,数据和ui应该在理论上分开,我定义了一个单独的类来处理配置数据。我的问题是如何在设置类中实例化数据类。

一种方法是在调用者对象中创建数据类,我的意思是调用设置菜单类的对象。

我的问题涉及的另一种方法是在settings类中创建一个DATA类变量。我怀疑当设置类被销毁时会发生什么!设置类中的数据类对象是否也会被销毁?如果它被定义为设置类的静态成员呢?

#ifndef SETTINGSWINDOW_H

#define SETTINGSWINDOW_H

#include <QMainWindow>
#include <QModelIndex>

#include <QSignalMapper>
#include <QRadioButton>
#include <QSpinBox>
#include <QTimer>

#include "cameracommands.h"

struct Config
{
    /* General Options */
    QString general_key_lock;
    QString general_back_light;
};

//class IConfigSource
//{
//public:
//    virtual Config config() const;
//    virtual void setConfig(const Config& cfg);
//};

class ConfigSource /* : public IConfigSource*/
{
    public:

    ConfigSource() {

        config_.general_back_light         = "OFF";
        config_.general_key_lock           = "OFF";
    }

    Config config() const {return config_;}

    void setConfig(const Config& cfg) {config_ = cfg;}

    private:

    Config config_;
};

class ConfigUpdater : public QObject
{
    Q_OBJECT
public:
    ConfigUpdater(ConfigSource& src) : src_(src) {}

public slots:

    void apply () {src_.setConfig(tempConfig_);}
    void cancel() {tempConfig_ = src_.config();}

public:

    void updateGeneralBackLight(QString s)             {tempConfig_.general_back_light         = s; qDebug() << "BackLight updated :)";}
    void updateGeneralKeyLock(QString s)               {tempConfig_.general_key_lock           = s; qDebug() << "KeyLock updated :)";}

    Config tempConfig_;
    ConfigSource& src_;
};

//----------------------------

namespace Ui {
    class SettingsWindow;
}

class SettingsWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit SettingsWindow(QWidget *parent = 0);

    ~SettingsWindow();

signals:
    void clicked(const QString &text);
    void sendToPLC(QByteArray );

public slots:
    void updateGeneralBackLight();
    void updateGeneralKeyLock();

    void getRow(QModelIndex);
    void MySlot(QString);

private slots:
    void on_pushButton_5_clicked();
    void on_pushButton_3_clicked();

private:

    void set_mappings();

    Ui::SettingsWindow *ui;
    ConfigUpdater      *config_updater;
    QSignalMapper      *mapper;
};

#endif // SETTINGSWINDOW_H

这是来源:

QMainWindow(parent),
ui(new Ui::SettingsWindow)

{     / *初始化* /

ui->setupUi(this);

ConfigSource src;

config_updater = new ConfigUpdater(src);

3 个答案:

答案 0 :(得分:1)

这取决于你如何使用它。

  • 场景1.程序运行时,需要在内存中保存设置。

  • 场景2.需要立即将设置保存到光盘,然后按需读取。

在方案1 中,您需要始终能够访问内存中的数据。因此,最好将settingsUI类和settingsData类分开,这样您就可以访问后者了。

class settingsUI
{
<...>
private:
    settingsData * data;//pointer to the data object
}

class settingsData
{
}

在方案2 中,您可以将settingsData聚合到settingsUI中,并在销毁用户界面时将数据保存到文件中。

class settingsUI
{
public:
    <...>
    ~settingsUI();

private:
    class settingsData
    {
    <..>
    }data;
<...>
}

class settingsUI::~settingsUI()
{
    data.saveToFile();
}

是的,如果您将设置聚合到UI中,它将在销毁UI时被销毁。将数据保存为静态成员并不是最好的主意,最好将数据与可视化表示(在您的情况下是UI类)分开。

<强> UPD

如果你想在程序退出之前保留它,我建议你保存一个指向UI类中数据的静态指针。下面是一个使用原始指针的示例,但您也可以使用智能指针,ofc。

class data
{
}

class UI
{
private:
    static data * data_;
}
data* UI::data_;

当您的程序启动时,为数据分配内存:UI::data_ = new data(),当程序结束时(或者如果您不再需要数据),请释放内存:delete UI::data_。再一次,最好使用智能指针,所以这只是一个例子。

答案 1 :(得分:0)

是的,当销毁设置对象时,数据对象将被销毁。如果你把它变成静态成员那么它就不会。但这可能不是一个好主意。更好的方法是将数据对象保存到文件中(比方说)。您可以在设置对象构造函数中读取该文件,并将该文件写入设置对象析构函数。

修改

class SettingsWindow : public QMainWindow
{
Q_OBJECT

public:
    explicit SettingsWindow(ConfigSource& src , QWidget *parent = 0);
...
}

SettingsWindow::SettingsWindow(ConfigSource& src , QWidget *parent)
    QMainWindow(parent),
    ui(new Ui::SettingsWindow)
{
    ui->setupUi(this);
    config_updater = new ConfigUpdater(src);
    ...
}
谢谢,这是对的。当我尝试将以下变量传递给用户定义的函数时,程序终止: (内部标题)

void print_config(Config cfg);

Ui :: SettingsWindow * ui; ConfigUpdater * config_updater;

在cpp内:

void SettingsWindow::print_config(Config config)
{
    qDebug() << config.general_back_light;
    qDebug() << config.general_key_lock;

}

void SettingsWindow::on_sendToMainButton_clicked() /* cancel */
{
   print_config(config_updater->tempConfig_);
   print_config(config_updater->src_.config());
}

第一个,print_config指令工作正常,对于tempConfig_,但是当我在第二个语句中传递src_时,它跳出outta program。

// ------------

我知道问题的来源,但我无法解决,我希望这可以提供帮助:

class ConfigUpdater : public QObject
{
    Q_OBJECT
public:
    ConfigUpdater(ConfigSource& src) : src_(src) {}

public slots:

    void apply () {src_.setConfig(tempConfig_);}
    void cancel() {tempConfig_ = src_.config();}

public:

    Config tempConfig_;
    ConfigSource& src_;
};

这里,src_在任何地方都被引用传递,即使在Settings窗口的构造函数中也是如此。 当我尝试在内存中访问它时程序失败,例如:

config_updater->cancel();

其中:     void cancel(){tempConfig_ = src_.config();}

答案 2 :(得分:0)

如果设置类仅由UI使用,则将其保留在UI类中是有意义的:

class Settings {
    int a;
    int b;
};

class Ui {
private:
    Settings settings;
};
settings的销毁过程中,

Ui将被销毁。

如果您在许多地方使用Settings对象,那么保持共享指针更有意义:

class Ui {
public:
    Ui(std::shared_ptr<Settings> someSettings)
        : settings(someSettings)
    {}
private:
    std::shared_ptr<Settings> settings;
};

Settings的最后一个所有者被销毁时,此shared_ptr对象将被销毁。