信號與槽
- connect函數參數中‘槽函數實參’沒有聲明爲slots時,編譯不會報錯,但是也不會起作用(被執行)。
- 注意qt4和qt5兩種版本下connect函數中信號和槽函數的形參不同。
- 使用qt5語法時,若信號存在重載,則connect函數編譯時會報錯,不能準確的與槽函數(形參格式)相匹配!這時要麼用qt4形式,要麼通過static_cast方法進行數據類型裝換,如:
(將QButtonGroup::buttonClicked強制裝換爲形參是int的那個)
參考:https://blog.csdn.net/f_zyj/article/details/82018147 - C++中"A:: "的意思:指向類A中任意元素的指針(變量、方法),如:
int A:: point_i2,表示point_i2是一個指向類A中int變量的指針;
如果A::fun存在重載,則:static_cast<void (A:😗)(int)>(&fun):表示將fun函數指針強制裝換爲類A中形參格式爲int的那個重載函數的函數指針。(有歧義,待改正)
- qt中使用資源文件時,如果編譯提示:
原因:一般由於文件資源路徑改動後導致。
解決辦法:將工程目錄下對應工程的Debug文件刪除,重新編譯工程即可。 - 在爲button和form設置icon時,icon的路徑沒有問題,但就是不顯示icon內容,刪除debug文件夾也無效,後來在qt creater中刪除*.qrc資源樹下導入的文件,重新添加後恢復正常,不知道以後會不會再遇到!
- C++中靜態成員(變量和方法)的作用、理解及其使用(不需要依賴具體的對象)
創建對象:使用和不使用new
- 不使用new關鍵字(
QLabel label1;
):新建的對象位於棧中,屬於局部變量,在函數結束後被自動銷燬; - 使用new關鍵字(
QLabel *label2=new QLabel;
):新建的對象位於堆中,生命週期通常比棧中變量長,需要手動釋放。 - 下面通過4種形式分別測試在不同位置創建QPushButton對象,對應的現象:
- 在類的構造函數中不使用new創建:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
// QPushButton btn1("btn1", &w);
// QPushButton *btn2=new QPushButton("btn2", &w);
w.show();
return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//
QPushButton btn1("btn1", this);
// QPushButton *btn2=new QPushButton("btn2", this);
}
MainWindow::~MainWindow()
{
delete ui;
}
運行結果:按鈕未顯示
- 在類的構造函數中使用new創建:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
// QPushButton btn1("btn1", &w);
// QPushButton *btn2=new QPushButton("btn2", &w);
w.show();
return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//
// QPushButton btn1("btn1", this);
QPushButton *btn2=new QPushButton("btn2", this);
}
MainWindow::~MainWindow()
{
delete ui;
}
運行結果:按鈕正常顯示
- 在main函數中不使用new創建:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
QPushButton btn1("btn1", &w);
// QPushButton *btn2=new QPushButton("btn2", &w);
w.show();
return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//
// QPushButton btn1("btn1", this);
// QPushButton *btn2=new QPushButton("btn2", this);
}
MainWindow::~MainWindow()
{
delete ui;
}
運行結果:按鈕正常顯示
- 在main函數中使用new創建:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
// QPushButton btn1("btn1", &w);
QPushButton *btn2=new QPushButton("btn2", &w);
w.show();
return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//
// QPushButton btn1("btn1", this);
// QPushButton *btn2=new QPushButton("btn2", this);
}
MainWindow::~MainWindow()
{
delete ui;
}
運行結果:按鈕正常顯示
經測試發現:通過new關鍵字在堆上創建對象時,無論是在類的函數中還是在main函數中,都可以正常顯示;不使用new關鍵字在類的函數中創建對象時,對象不可見,因爲在類函數執行結束後,對象也被銷燬;不使用new關鍵字在main函數中創建對象時,對象也可見,因爲當前對象的聲明週期是在main函數內,而main函數因爲return a.exec();
的存在而不會退出;最後我們再做個測試:
- 在main函數中不使用new創建,但放置在函數體中:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
do{
QPushButton btn1("btn1", &w);
}while(0);
// QPushButton *btn2=new QPushButton("btn2", &w);
w.show();
return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//
// QPushButton btn1("btn1", this);
// QPushButton *btn2=new QPushButton("btn2", this);
}
MainWindow::~MainWindow()
{
delete ui;
}
運行結果:按鈕不顯示
和預料中一樣,對象在do…while的花括號結束後就被銷燬了,所以不可見。
創建對象但不指定parent時的現象
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
// do{
// QPushButton btn1("btn1", &w);
// }while(0);
QPushButton *btn2=new QPushButton("btn2", &w);
QPushButton *btn3=new QPushButton("btn3");
btn3->show();
w.show();
return a.exec();
}
結果:
- 這兩個窗體是不是模態的,相互可以疊加,各自的按鈕也可以單獨按下;
- 關閉其中任意一個,程序都不會結束,除非兩個窗體都關閉。
待研究。。。
父、子對象析構順序測試
- 先在棧中定義子對象,再定義父對象,子對象再綁定父對象:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
#include <QMenuBar>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton btn1("btn1");
// QPushButton *btn3=new QPushButton("btn3");
MainWindow w;
btn1.setParent(&w);
// btn3->setParent(&w);
w.show();
return a.exec();
}
關閉窗口後,程序崩潰。
- 先定義父對象,再在棧中定義子對象,子對象再綁定父對象:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
#include <QMenuBar>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// QPushButton *btn3=new QPushButton("btn3");
MainWindow w;
QPushButton btn1("btn1");
btn1.setParent(&w);
// btn3->setParent(&w);
w.show();
return a.exec();
}
關閉窗口後,程序正常結束。
- 先在堆中定義子對象,再定義父對象,子對象再綁定父對象:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
#include <QMenuBar>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// QPushButton btn1("btn1");
QPushButton *btn3=new QPushButton("btn3");
MainWindow w;
// btn1.setParent(&w);
btn3->setParent(&w);
w.show();
return a.exec();
}
關閉窗口後,程序正常結束。
- 先定義父對象,再在堆中定義子對象,子對象再綁定父對象:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
#include <QMenuBar>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// QPushButton btn1("btn1");
MainWindow w;
// btn1.setParent(&w);
QPushButton *btn3=new QPushButton("btn3");
btn3->setParent(&w);
w.show();
return a.exec();
}
關閉窗口後,程序正常結束。
分析(局部對象的析構順序應該按照其創建順序的相反過程):
1. 在堆上創建的對象不論創建順序前後,程序都會正常結束;
2. 如果在棧上創建的子對象比父對象先創建,在父對象先調用析構函數且釋放其所有子對象後,子對象的析構函數再次被調用,所以造成程序異常崩潰;
3. 在棧上創建的子對象在父對象之後創建,則會先調用子對象的析構函數將其從父對象 window 的子對象列表中刪除,然後纔會再調用 window 的析構函數,程序正常結束。
結論:
- 在棧上創建子對象時就綁定父對象,在父對象還不存在時編譯器會報錯,起到提示作用,避免程序運行後才感知到錯誤。
- 儘量在堆上創建子對象,可以避免定義的順序問題。