1.C++ 中的静态(static)类成员函数具有以下特性:
-
独立于任何对象:静态成员函数不依赖于类的实例或对象。它们可以在没有类的实例的情况下直接访问和调用,可以通过类名访问。
-
不访问非静态成员:静态成员函数只能访问类中的静态成员变量和其他静态成员函数。它们无法直接访问非静态成员变量或非静态成员函数,因为这些成员是与类的实例相关联的。
-
作用域属于类:静态成员函数属于整个类而不是特定的对象。因此,在使用时,可以通过类名加上作用域解析运算符
::
直接调用静态成员函数,而无需创建类的实例。 -
在类的所有实例之间共享:静态成员函数属于类本身,而不是类的实例。因此,静态成员变量和静态成员函数在所有类的实例之间共享相同的值。修改一个实例的静态成员变量会影响到其他所有实例。
class DataBase
{
public:
static getSum(int i, int j);//类中的一个静态成员函数
}
cout << DataBase::getsum(1,2); << endl;//直接通过类名调用不用实例化类
2.在Qt中信号与槽多次关联会怎么样
在 Qt 框架中,信号与槽是一种实现对象之间通信的机制。当一个信号与多个槽进行关联时,会按照特定的规则进行处理。
-
多个槽函数会按照连接的顺序被依次调用:当一个信号被触发时,与之关联的多个槽函数会按照它们被连接的顺序被依次调用。
-
如果槽函数返回值为
void
,那么多个槽函数的返回值将被忽略。 -
如果某个槽函数返回值类型不是
void
,并且有多个槽函数与同一个信号关联,那么只有最后一个槽函数的返回值会被使用。
所以在某些情况下,多个槽函数的执行顺序可能会影响程序的逻辑和结果。
class MyClass : public QObject
{
Q_OBJECT
public slots:
void slot1() {
cout << "Slot1" << endl;
}
void slot2() {
cout << "Slot2" << endl;
}
};
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
MyClass obj;
// 将信号 signal同时关联到两个不同的槽函数
QObject::connect(&obj, &MyClass::destroyed, &obj, &MyClass::slot1);
QObject::connect(&obj, &MyClass::destroyed, &obj, &MyClass::slot2);
emit obj.destroyed();
return app.exec();
}
运行后会依次调用两个slot槽函数输出
3.qt中同一个信号与同一个槽重复绑定会怎么样
重复绑定同一个信号和槽可能会导致以下问题:
-
槽函数被多次调用:当信号触发时,每个绑定的槽函数都会被调用一次。如果同一个槽函数被重复绑定了多次,那么它将在每次信号触发时被多次调用。这可能会导致逻辑错误或产生意外的行为。
-
难以预测的执行顺序:多个槽函数可能以不确定的顺序被调用,这取决于它们被绑定的顺序。如果多个槽函数对同一数据进行操作,执行顺序的不确定性可能导致数据不一致或竞争条件。
-
性能损耗:每个绑定的槽函数都会被调用,因此重复绑定会增加额外的函数调用开销和处理时间。如果重复绑定的次数过多,可能会降低程序的性能。
为了避免以上问题,建议在绑定信号和槽时注意确保只绑定一次,或者在绑定前检查是否已经存在绑定关系,避免重复绑定相同的信号和槽。也可以使用 QObject::disconnect()
函数来解除先前的绑定关系,确保只有一个正确的绑定关系存在。
#include <QPushbutton>
int g_val = 0;
class TestObject : public QPushButton {
Q_OBJECT
public slots:
void addvalue() {
g_val += 10;
std::cout << "当前g_val = " << globalVariable << endl;
}
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QPushButton button;
QObject::connect(&button, &button::click(), button,&TestObject::addToGlobalVariable);
QObject::connect(&button, &button::click(), button,&TestObject::addToGlobalVariable);
emit testObject.addToGlobalVariable();
return app.exec();
}
像如此会多次调用addvalue函数导致结果超出预期。
4.#include "" <>区别
#include是预处理指令,用于在源代码中引入外部头文件#include 使用尖括号 <>或双引号 "" 来包含头文件,它们之间有以下区别
-
#include<header>使用尖括号来包含头文件时,编译器会从系统的标准库目录中查找该头文件。这些标准库的路径是由编译器的设置决定的,通常包含了标准的 C++ 和操作系统相关的头文件。
-
#include "header"
:使用双引号来包含头文件时,编译器首先会在当前源文件所在的目录中查找该头文件。如果在当前目录中找不到该头文件,则会继续在其他相关目录中查找,如通过编译选项指定的附加目录等。相比起尖括号形式,这种方式更适合引入用户自定义的头文件或项目内部的头文件。
在一个Qt项目中如果你的项目中有自定义的头文件,且这些头文件位于项目目录或子目录下,那么你应该使用双引号形式的 #include "header"
来引入这些头文件。因为这样可以告诉编译器在当前源文件所在的目录和相关目录中查找这些自定义头文件。
如果你使用尖括号形式的 #include <header>
来引入自定义头文件,编译器会从系统标准库目录中查找该头文件,很可能无法找到对应的自定义头文件。
反之亦是如此。
5.多为多态基类申明virtual 析构函数
在多态情况下,当基类指针指向派生类对象时,通过基类指针调用析构函数会触发动态绑定(或称为运行时多态)。如果基类的析构函数不被声明为虚函数,那么在使用基类指针删除派生类对象时,只会调用基类的析构函数,而不会调用派生类的析构函数。这可能导致派生类特有的资源无法正确释放,造成内存泄漏和程序行为的不确定性。
当基类的析构函数被声明为虚函数时,它能够确保在使用基类指针删除派生类对象时,会首先调用派生类的析构函数,然后再调用基类的析构函数。这样就可以保证派生类特有的资源会被正确地释放掉,避免了内存泄漏的问题。
因此,为多态基类声明虚析构函数的好处是,在删除通过基类指针指向的派生类对象时,能够正确地调用派生类和基类的析构函数,从而实现对象的正确销毁和资源的正确释放。这是应对多态性需求下的安全做法,能够保证程序的合理性和可靠性。
#include <iostream>
class BaseClass
{
public:
virtual ~BaseClass ()
{
std::cout << "Base destory" << std::endl;
}
};
class SubClass: public BaseClass
{
public:
~SubClass()
{
std::cout << "SubClass destory" << std::endl;
}
};
int main()
{
Base* ptr = new Derived();//用派生类去创建基类的对象
delete ptr;//在析构时先调用派生类对象的析构再调用基类的
return 0;
}