C ++类中的引用

时间:2017-04-24 13:07:49

标签: c++ qt reference

我是编程新手。我无法理解如何引用另一个类的方法。

我有几个文件和类:

的main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow w;
    w.show();
    return app.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtCore/QtGlobal>
#include <QMainWindow>

QT_BEGIN_NAMESPACE

namespace Ui {
class MainWindow;
}

QT_END_NAMESPACE

class Valve;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    void openValve(int id);
    void closeValve(int id);


private:
    Ui::MainWindow *ui;
    Settings *settings;
    Valve *valve;
};

class A {
...
private:
void start();
}
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::CustomizeWindowHint);
    this->setFixedSize(this->geometry().width(),this->geometry().height()); 

    //класс для 7 клапанов
    valve = new Valve(7);
}

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

void MainWindow::valveSwitch(int id)   
{
    if (valve->getState(id))
        closeValve(id);
    else
        openValve(id);
}

void MainWindow::openValve(int id)
{
    QString str = "Valve №" + QString::number(id);
    valveButton[id-1]->setEnabled(false);
    if (valve->open(id)) {
        valveButton[id-1]->setEnabled(true);
        //valveButton[id-1]->setPalette(QPalette(Qt::green));
        //valveButton[id-1]->setStyleSheet(VALVE_OPEN_COLOR);
        QString style = QString(DEFAULT_STYLE_BUTTON) + QString(DEFAULT_BACKGROUND_BUTTON);
        valveButton[id-1]->setStyleSheet(style);
        ui->mainLabel->setText(str + " open! :)");
    }
    else {
        valveButton[id-1]->setEnabled(true);
        ui->mainLabel->setText("Cant open " + str);
        remoteDisconnect();
    }
}
void MainWindow::closeValve(int id)
{
    QString str = "Valve №" + QString::number(id);
    valveButton[id-1]->setEnabled(false);
    if (valve->close(id)) {
        valveButton[id-1]->setEnabled(true);
        //valveButton[id-1]->setPalette(style()->standardPalette());
        valveButton[id-1]->setStyleSheet("");
        ui->mainLabel->setText(str + " close! :)");
    }
    else {
        valveButton[id-1]->setEnabled(true);
        ui->mainLabel->setText("Cant close " + str);
        remoteDisconnect();
    }
}
A::A
{
}
A::~A
{
}
void A::start()
{
//MainWindow::openValve(2);
//valve.open(3);
}

如何从A类访问MainWindow类方法openValve / closeValve? 或者如何从A类访问MainWindow构造函数的类 Valve 的实例 valve

3 个答案:

答案 0 :(得分:1)

您应该将MainWindow对象传递到A::start方法:

class A {
...
private:
    void start(MainWindow & w);
}

void A::start(MainWindow & w) {
    w._MainWindow_method_name_here_();
}

或者你应该在MainWindow class:

中声明一个静态方法
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    static void aStaticMethod();
};

void MainWindow::aStaticMethod() {
    ...
}

void A::start() {
    MainWindow::aStaticMethod();
}

要访问MainWindow的受保护/私有方法,您应该将A类声明为MainWindow的朋友:

class MainWindow : public QMainWindow
{
    friend class A;
    ...
};

<强>更新

  

我创建了一个新类,使其在单独的线程中工作,并从主类中调用其方法(通过单击按钮)。因此,我需要A级来打开/关闭阀门等。

“真正的Qt方式”是使用signals & slots机制。

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

// Transform open/closeValve methods into slots
// (a method that can be assigned as an event handler)
//
public slots:
    void openValve(int id);
    void closeValve(int id);

private:
    Ui::MainWindow *ui;
    Settings *settings;
    Valve *valve;
};


// This class should be a descendant of QObject
//
class A : public QObject
{
    Q_OBJECT

// Transform this method to a slot, so it can be called
// as regular method, or can be assigned as an event handler,
// for instance, as QPushButton::click handler.
//
public slots:
    void start();

// Add signals
//
signals:
    void openValveSignal(int id);
    void closeValveSignal(int id);
}

void A::start()
{
    // do something and then emit the signal to open valve,
    // MainWindow::openValve(2) will be called
    emit openValveSignal(2);
    ...
    // do something and then emit the signal to close valve,
    // MainWindow::closeValve(3) will be called
    emit closeValveSignal(3);
}


// connects A signals with MainWindow slots,
// so when you `emit A::***Signal()` then corresponding
// `MainWindow::***` method will be called
//
void initialize(MainWindow * pWnd, A * pA)
{
    QObject::connect(pA, &A::openValveSignal, pWnd, &MainWindow::openValve);
    QObject::connect(pA, &A::closeValveSignal, pWnd, &MainWindow::closeValve);
}

您可以像往常一样从a->start()方法调用MainWindow方法。或者,您可以使用clicked方法连接按钮A::start信号,例如:

void initialize(MainWindow * pWnd, QAbstractButton * pBtn, A * pA)
{
    // C++11 lambda function is used here because A::start has no arguments
    QObject::connect(pBtn, &QAbstractButton::clicked, [pA](){ pA->start(); });

    QObject::connect(pA, &A::openValveSignal, pWnd, &MainWindow::openValve);
    QObject::connect(pA, &A::closeValveSignal, pWnd, &MainWindow::closeValve);
}

因此,当您单击按钮时,将自动调用A::start方法。然后将MainWindow::open/closeValve方法调用A::start方法。

答案 1 :(得分:1)

//MainWindow::openValve(2);
//valve.open(3);

最初:

openValve不是静态的,所以你需要一个MainWindow实例才能调用它:

MainWindow* mw_ex0;
// alternatively, if more appropriate:
MainWindow& mw_ex1;

mw_ex0->openValve(2);
mw_ex1.openValve(2);

MainWindow实例可以是函数start的参数,也可以是类A的成员变量 - 具体取决于您的具体需求。

如果您想要访问阀门成员(阀门是指针,因此您需要operator-&gt;),同样适用:mw_ex0->valve->open(3);mw_ex1.valve->open(3);)。

但是,您需要授予对当前私有成员的A类访问权限;三个选项:

  1. 创建一个MainWindow的朋友类 - 这允许A访问MainWindow的私有成员(如果open不公开,也可以申请Valve类。)
  2. 将相应的函数设为public(MainWindow :: openValve和Valve :: open);为了访问MainWindow的阀门成员,你也可以公开它,但一般不建议将类的内部公开给外界 - 有人可能只是改变你的阀门成员还有别的东西 - 你的程序坏了...所以请为。提供一个简单的getter。
  3. 创建一个MainWindow的内部类。然后它隐式地访问它的外部类成员(取决于类A的要求,这可能不合适 - 由你决定......)。
  4. 图片的标题说明:

    • 在构造函数中,您不初始化settings成员。
    • 您不会清理析构函数中的阀门成员(潜在的内存泄漏)。

    为了避免必须清理,您可以直接在您的班级中加入阀门 - 这并不总是合适,但在这里可能是一个不错的选择(由您决定,只是显示替代方案):

    class MainWindow
    {
        Valve valve;
    };
    
    MainWindow::MainWindow()
        : valve(7) // calls constructor directly
    { }
    

    请注意,您现在使用运算符。访问阀门的成员(mw_ex0->valve.open(3);)。优点是Valve不会与MainWindow一起自动清理。或者,可以使用std::unique_ptr来保存指向Valve实例的指针,然后也可以自动清理。

答案 2 :(得分:0)

openValve声明为公共方法,将valve声明为公共对象(open也必须公开)

然后用作:

MainWindow mainWindow;

mainWindow.openValve(2);
mainWindow.valve.open(3);