Qt元对象系统 day5

news2024/9/29 3:34:03

Qt元对象系统 day5

内存管理

  • QObject以对象树的形式组织起来,当为一个对象创建子对象时,子对象回自动添加到父对象的children()列表中。父对象拥有子对象所有权,比如父对象可以在自己的析构函数中删除它的孩子对象。使用findChild()或findChildren()通过名字和类型查询孩子对象
QObject(QObject *parent = nullptr)
  • QObject及其派生类的对象,如果其parent非nullptr,那么其parent析构时会析构该对象。

  • 父子关系:父对象、子对象、父子关系。这是Qt中所特有的,与类的继承关系无关,传递参数是与parent有关(基类、派生类,或父类、子类,这是对于派生体系来说的,与parent无关)。

  • 在Qt中,最基础和核心的类是:QObject,QObject内部有一个名为children的QObjectList列表,会保存所有子对象,还有一个指针parent,用来指向父对象,当自己析构时,会先把自己从parent列表中删除并且析构所有的children。

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>

//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG
    #pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else
    #pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUG

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    {
        QRadioButton* rBtn = new QRadioButton("男", &w);
        //设置对象名
        rBtn->setObjectName("man_rBtn");
        auto btn = new QPushButton("小瓜");
        //设置对象名
        btn->setObjectName("小瓜_大瓜");

        //如果指定了父对象,则不需要手动show
        btn->setParent(&w);
        rBtn->move(100, 0);
        QObject::connect(btn, &QPushButton::clicked, []()
            {
                qDebug() << "小瓜";
            });
        //获取btn的父对象
        auto parentw = dynamic_cast<QWidget*>(btn->parent());
        //是否获取成功
        if (parentw)
        {
            qDebug() << parentw;
        }
        //获取子对象列表
        const QObjectList& list = w.children();
        for (auto v : list)
        {
            qDebug() << v;
        }
        //查找指定类型的子对象
        qDebug() << "sub object" << w.findChild<QPushButton*>();
        //查找指定的子对象名的子对象
        qDebug() << w.findChild<QWidget*>("小瓜_大瓜");
    }
    //把所有子对象添加到窗口之后再显示窗口
    w.show();
    return a.exec();
}
  • 运行结果
    在这里插入图片描述

释放内存

  • Qt里面有些还是得手动释放
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>

//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG
    #pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else
    #pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUG



int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    auto w = new QWidget;
    w->show();
    QObject::connect(w, &QObject::destroyed, []() {
            qDebug() << "释放成功";
        });
    int ret = a.exec();
    //1.直接使用delete释放(对于直接或间接继承QObject的类对象)
    delete w;
    //2.使用QOBject提供的安全释放的函数来释放对象(下一次运行到事情循环的时候,才去释放对象)
    //w->deleteLater(); //此处场景不能使用,因为事件循环已经结束了,当某个窗口不需要的时候就释放掉用这个
    return ret;
}

  • 运行结果
    在这里插入图片描述

Qt中的智能指针

  • 为了管理内存等资源,C++程序员通常采用RAII(Resource Acquisition Is Initialization)机制:在类的构造函数中申请资源,然后使用,最后在析构函数中释放资源。
  • 如果没有智能指针,程序员必须保证new对象能在正确的时机delete,四处编写异常捕获代码以释放资源,而智能指针则可以在退出作用域时(不管是正常流程离开或是因异常离开)总调用delete来析构在堆上动态分配的对象。
  • Qt中的智能指针:
智能指针描述
QPointer[QObject专享指针]QObject或子类对象释放时会自动指向nullptr
QScopedPointer[独享指针]超出作用域自动释放管理的对象
QSharedPointer[共享指针]
QWeakPointer[监视指针]
QScopedArrayPointer[独享数组指针]超出作用域自动释放管理的对象数组
QSharedDataPointer[隐式共享指针]读时共享,写时拷贝
QExplicitlySharedDataPointer[显示共享指针]读时共享,写时需要手动拷贝(通过detach()函数)

QPointer

  • 受保护指针QPointer的行为类似于普通c++指针T *,只是当被引用的对象被销毁时它会自动清除(不像普通c++指针,在这种情况下它会变成“悬浮指针”)。T必须是QObject的子类。
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>
#include <QPointer>
//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG
    #pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else
    #pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUG

class Text :public QWidget
{
    Q_OBJECT
public:
    Text(QWidget* parent = nullptr) :QWidget(parent)
    {
        text_QPointer();
    }
    void text_QPointer()
    {
        //QPointer不会自动释放保存的对象
        QPointer btn = new QPushButton("小瓜", this);
        if (btn)
        {
            qDebug() << "小瓜";
        }
        delete btn;//释放之后,btn会自动变为nullptr
        if (!btn)
        {
            qDebug() << "小瓜不见了";
        }
    }
};

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    Text w;
    w.show();

    return a.exec();
    
}

#include "main.moc"
  • 运行结果
    在这里插入图片描述

QScopedPointer

  • 手动管理堆分配对象非常困难而且容易出错,通常的结果是代码泄漏内存并且难以维护。QScopedPointer是一个小型实用程序类,它通过将基于堆栈的内存所有权分配给堆分配(更通常称为资源获取初始化(RAII)),极大地简化了这一点。

  • QScopedPointer保证当当前作用域消失时,所指向的对象将被删除。

QSharedPointer

  • QSharedPointer是c++中的一个自动共享指针。它的行为和普通指针完全一样。

  • 如果没有其他QSharedPointer对象引用它,当它超出作用域时,QSharedPointer将删除它所持有的指针。

  • QSharedPointer对象可以从一个普通指针、另一个QSharedPointer对象或通过将QWeakPointer对象提升为强引用来创建。

QWeakPointer

  • 在c++中,QWeakPointer是对指针的自动弱引用。它不能用于直接解引用该指针,但可以用于验证该指针是否已在另一个上下文中被删除。

  • QWeakPointer对象只能通过从QSharedPointer赋值来创建。

QScopedArrayPointer

  • QScopedArrayPointer是一个QScopedPointer,默认使用delete[]操作符删除它所指向的对象。为了方便,它还提供了操作符[]

QSharedDataPointer

  • QSharedDataPointer类表示指向隐式共享对象的指针。

  • QSharedDataPointer使您可以轻松地编写自己的隐式共享类。QSharedDataPointer实现了线程安全的引用计数,确保将QSharedDataPointer添加到可重入类中不会使它们不可重入。

  • 许多Qt类都使用隐式共享,以将指针的速度和内存效率与类的易用性结合起来。有关更多信息,请参见共享类页面。

  • 假设您想让Employee类隐式共享。这个过程是:定义Employee类,使其拥有类型为QSharedDataPointer的单个数据成员。

  • 定义从QSharedData派生的EmployeeData类,以包含通常放入Employee类中的所有数据成员。

QExplicitlySharedDataPointer

  • QExplicitlySharedDataPointer类表示指向显式共享对象的指针。

  • QExplicitlySharedDataPointer使您可以轻松编写自己的显式共享类。QExplicitlySharedDataPointer实现了线程安全的引用计数,确保将QExplicitlySharedDataPointer添加到可重入类中不会使它们不可重入。

  • 除了一个很大的区别,QExplicitlySharedDataPointer就像QSharedDataPointer。最大的区别是,QExplicitlySharedDataPointer的成员函数在允许修改共享数据对象之前,不像QSharedDataPointer的非const成员那样在写操作(detach())时自动复制。有一个detach()函数可用,但如果您真的想要detach(),则必须自己调用它。这意味着QExplicitlySharedDataPointers的行为与常规的c++指针类似,只是通过进行引用计数并且在引用计数为0之前不删除共享数据对象,避免了悬浮指针的问题。

属性系统

  • Qt提供了一个复杂的属性系统,类似于一些编译器供应商提供的属性系统。然而,作为一个独立于编译器和平台的库,Qt不依赖于像__property或[property]这样的非标准编译器特性。Qt解决方案可以在Qt支持的每一个平台上使用任何标准的c++编译器。它基于元对象系统,也通过信号和插槽提供对象间通信。

  • 属性的行为类似于类数据成员,但它具有通过元对象系统访问的附加特性。

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>
#include <QPointer>
//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG
    #pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else
    #pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUG
 
class Person :public QObject
{
    Q_OBJECT
public:
    Person()
    {

    }
};

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    Person xiaogua;
    //1.通过方法设置一些成员变量
    xiaogua.setObjectName("小瓜");
    qDebug() << xiaogua.objectName();
    //2.通过属性来设置
    xiaogua.setProperty("objectName", "大瓜");
    qDebug() << xiaogua.objectName() << xiaogua.property("objectName");

    //3.如果设置类里面没有的属性,那么则会添加临时的属性
    xiaogua.setProperty("name", "小瓜");
    xiaogua.setProperty("age", 21);
    qDebug() << xiaogua.property("name") << xiaogua.property("age");

    return a.exec();
    
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

声明自己的属性

  • 除了通过setProperty动态添加属性之外,怎样才能在代码中,声明属性呢?

  • 要声明属性,请在继承 QObject 的类中使用 Q_PROPERTY() 宏。

Q_PROPERTY(type name
            (READ getFunction [WRITE setFunction] |
             MEMBER memberName [(READ getFunction | WRITE setFunction)])
            [RESET resetFunction]
            [NOTIFY notifySignal]
            [REVISION int | REVISION(int[, int])]
            [DESIGNABLE bool]
            [SCRIPTABLE bool]
            [STORED bool]
            [USER bool]
            [BINDABLE bindableProperty]
            [CONSTANT]
            [FINAL]
            [REQUIRED])
  • 如果未指定 MEMBER 变量,则需要 READ 访问器函数。 它用于读取属性值。 理想情况下,const 函数用于此目的,它必须返回属性的类型或对该类型的 const 引用。 例如,QWidget::focus 是一个带有 READ 函数的只读属性,QWidget::hasFocus()。

  • WRITE 访问器函数是可选的。 它用于设置属性值。 它必须返回 void 并且必须只接受一个参数,该参数可以是属性的类型,也可以是指向该类型的指针或引用。 例如,QWidget::enabled 具有 WRITE 函数 QWidget::setEnabled()。 只读属性不需要 WRITE 函数。 例如,QWidget::focus 没有 WRITE 功能。

  • 如果未指定 READ 访问器函数,则需要 MEMBER 变量关联。 这使得给定的成员变量可读可写,而无需创建 READ 和 WRITE 访问器函数。 如果您需要控制变量访问,除了 MEMBER 变量关联之外,仍然可以使用 READ 或 WRITE 访问器函数。

  • RESET 功能是可选的。 它用于将属性设置回其特定于上下文的默认值。 例如,QWidget::cursor 有典型的 READ 和 WRITE 函数,QWidget::cursor() 和 QWidget::setCursor(),它还有一个 RESET 函数,QWidget::unsetCursor(),因为没有调用 QWidget:: setCursor() 可以表示重置为特定于上下文的光标。 RESET 函数必须返回 void 并且不带任何参数。

  • NOTIFY 信号是可选的。 如果已定义,则应指定该类中的一个现有信号,该信号在属性值更改时发出。 MEMBER 变量的 NOTIFY 信号必须采用零个或一个参数,该参数必须与属性的类型相同。 该参数将采用属性的新值。 NOTIFY 信号只应在属性真正被更改时发出,以避免在 QML 中不必要地重新评估绑定,例如。 当没有显式设置器的 MEMBER 属性需要时,Qt 会自动发出该信号。

  • REVISION 编号或 REVISION() 宏是可选的。 如果包含,它定义了要在 API 的特定修订版中使用的属性及其通知信号(通常用于暴露于 QML)。 如果不包含,则默认为 0。

  • DESIGNABLE 属性指示该属性是否应在 GUI 设计工具(例如 Qt Designer)的属性编辑器中可见。 大多数属性都是可设计的(默认为 true)。 有效值为真和假。

  • SCRIPTABLE 属性指示脚本引擎是否可以访问此属性(默认为 true)。 有效值为真和假。

  • STORED 属性指示该属性是否应该被认为是独立存在的,或者取决于其他值。 它还指示在存储对象的状态时是否必须保存属性值。 大多数属性是 STORED 的(默认为 true),但例如,QWidget::minimumWidth() 的 STORED 为 false,因为它的值只是从属性 QWidget::minimumSize() 的宽度分量中获取的,它是一个 QSize。

  • USER 属性指示该属性是被指定为该类的面向用户的属性还是用户可编辑的属性。 通常,每个类只有一个 USER 属性(默认为 false)。 例如,QAbstractButton::checked 是(可检查)按钮的用户可编辑属性。 请注意,QItemDelegate 获取和设置小部件的 USER 属性。

  • BINDABLE bindableProperty 属性表明该属性支持绑定,并且可以通过元对象系统 (QMetaProperty) 设置和检查与该属性的绑定。 bindableProperty 命名 QBindable 类型的类成员,其中 T 是属性类型。 这个属性是在 Qt 6.0 中引入的。

  • CONSTANT 属性的存在表明属性值是常量。 对于给定的对象实例,常量属性的 READ 方法在每次调用时都必须返回相同的值。 对于对象的不同实例,该常数值可能不同。 常量属性不能有 WRITE 方法或 NOTIFY 信号。

  • FINAL 属性的存在表明该属性不会被派生类覆盖。 这在某些情况下可用于性能优化,但并非由 moc 强制执行。 必须注意永远不要覆盖 FINAL 属性。

  • REQUIRED 属性的存在表明该属性应该由该类的用户设置。 这不是由 moc 强制执行的,并且对于暴露给 QML 的类最有用。 在 QML 中,除非设置了所有 REQUIRED 属性,否则无法实例化具有 REQUIRED 属性的类。

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>
#include <QPointer>
//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG
    #pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else
    #pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUG
int g_tel=666;
class Person :public QObject
{
    Q_OBJECT
    //让成员变量暴露给属性
    Q_PROPERTY(QString name MEMBER m_name NOTIFY nameChanged)
    Q_PROPERTY(int age MEMBER m_age NOTIFY ageChanged)
    //直接定义属性
    Q_PROPERTY(quint64 tel READ getTel WRITE setTel RESET resetTel NOTIFY telChanged)

public:
    Person()
    {

    }
    //提供接口
    int age()const{ return m_age;}
    void setAge(int age) { m_age = age; }
    QString name() const { return m_name; }
    void setName(const QString& name) { m_name = name; }

    quint64 getTel()const { return g_tel; }
    void setTel(quint64 tel)
    {
        if (g_tel != tel)
        {
            g_tel = tel;
            emit telChanged(tel);
        }
    }
    void resetTel() { setTel(-1); }

signals:
    void telChanged(quint64 tel);
    void ageChanged(int age);
    void nameChanged();

protected:
    int m_age{};
    QString m_name{};
};

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    Person xiaogua;
    xiaogua.setName("小瓜");
    xiaogua.setAge(20);
    QObject::connect(&xiaogua, &Person::telChanged, [](quint64 tel)
        {
            qDebug() << "tel changed" << tel;
        });
    QObject::connect(&xiaogua, &Person::ageChanged, []()
        {
            qDebug() << "age changed";
        });
    QObject::connect(&xiaogua, &Person::nameChanged, []()
        {
            qDebug() << "name changed";
        });
    
    //xiaogua.setTel(12345678);
    xiaogua.setProperty("tel", QVariant());
    xiaogua.setAge(21);
    xiaogua.setProperty("name", "ccc");
    qDebug() << xiaogua.property("name") << xiaogua.property("age") << xiaogua.property("tel");
    return a.exec();
    
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

绑定属性

  • Qt提供了可绑定属性。可绑定属性是具有值或使用任何c++函数(通常是c++ lambda表达式)指定的属性。如果它们是使用c++函数指定的,那么当它们的依赖项发生变化时,它们就会自动更新。
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>
#include <QPointer>
#include<QProperty>
#include<QObjectBindableProperty>
//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG
    #pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else
    #pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUG

//1,在Qobject子类中使用绑定属性
struct Circle : public QObject
{
	Q_OBJECT
public:
	Circle()
	{
		//添加绑定
		area.setBinding([=]
			{
				return M_PI * radius * radius;
			});
	}
	//QProperty<int> radius{};
	//QProperty<qreal> area{};

signals:
	void radiusChanged();
	void areaCahnged();
public:
	Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(Circle, int, radius, 0, &Circle::radiusChanged);
	Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(Circle, qreal, area, 0, &Circle::areaCahnged);
};
//2,如果类没有继承自Qobject
struct Rect
{
	Rect()
	{
		area.setBinding([=]
			{
				return w * h;
			});
	}
	QProperty<int> w;
	QProperty<int> h;
	QProperty<int> area;
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Circle c;
	QObject::connect(&c, &Circle::areaCahnged, []
		{
			qDebug() << "areaChange";
		});

	c.radius = 23;
	qDebug() << c.area;

	Rect r;
	r.w = 5;
	r.h = 9;
	qDebug() << r.area;
	return a.exec();
}

#include "main.moc"

内省机制

  • 所谓内省是指面向对象语言的一种在运行期间查询对象信息的能力, 比如如果该语具有运行期间检查对象型别的能力,那么我们称它是型别内省(type intropection)的,型别内省可以用来实施多态。
  • Qt拓展了C++的内省机制,(实际上,它并没有采用C++的RTTI),而是提供了更为强大的元对象(meta object)机制,来实现内省。接下来,就让我们看看,Qt是如何扩展c++内省机制的。
  • 要深刻理解Qt的内省机制,首先理解QObjectQObject类是整个Qt对象模型的心脏,Qt对象模型最为核心的功能是提供一种无缝的对象通讯机制,即就是我们所熟知的信号和槽。QObject主要有三大职责: 内存管理、内省(intropection)与事件处理。本文将集中在在内省的讨论。以下代码介绍了QObject类提供的内省方法:
//判断该类是否继承自指定的类
bool inherits(const char *className) const;

QWidget* w = new QWidget;
w.inherits("QObject");		//true
w.inherits("QWidget");		//false
  • 示例
#include<QApplication>
#include<QWidget>
#include<QMetaEnum>
class Test
{
public:
	Test()
	{
		QWidget w;
		qDebug() << w.inherits("QObject");
		
		auto metaObject =  w.metaObject();
		qDebug()<<metaObject->className();
	}
};

//1,在命名空间中使用注册枚举
namespace Maye
{
	Q_NAMESPACE
	enum Type
	{
		Player,
		Enemy,
		Bullet
	};
	Q_ENUM_NS(Type)	//把枚举类型注册到元对象系统
}
//2,在类中注册枚举
struct Person : public QObject 
{
	Q_OBJECT
public:
	enum Identity
	{
		Student,
		Doctor,
		Teacher
	};
	Q_ENUM(Identity)
};
int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Test t;
	using namespace Maye;
	Type type = Player;
	qDebug() << type;	//0  Player

	Person::Identity id = Person::Doctor;
	qDebug() << id;


	//获取枚举信息
	QMetaEnum me = QMetaEnum::fromType<Person::Identity>();
	qDebug() << me.name() << me.keyCount();
	qDebug() << me.keyToValue("Teacher");
	qDebug() << me.valueToKey(Person::Doctor);


	return a.exec();
}
#include "main.moc"

QFlags

#include<QApplication>
#include<QFlags>
struct xiaogua : public QObject
{
	Q_OBJECT
public:
	enum AlignMent
	{
		Top = 1,
		Left = 1 << 2,
		Bottom = 1 << 3,
		Right = 1 << 4,
		Center = 1 << 5
	};
	Q_ENUMS(AlignMent)
		Q_DECLARE_FLAGS(AlignMentFlags, AlignMent)
		Q_FLAG(AlignMentFlags)
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);
	xiaogua::AlignMentFlags flags(xiaogua::Top | xiaogua::Left);
	if (flags.testFlag(xiaogua::Top))
	{
		qDebug() << "has top";
	}
	if (flags.testFlag(xiaogua::Left))
	{
		qDebug() << "has left";
	}

	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1073433.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么压缩ppt文件?

怎么压缩ppt文件&#xff1f;造成ppt文件体积太大的原因主要有两个&#xff1a;① 图片和媒体文件&#xff0c;PPT中使用高分辨率、大尺寸的图片或视频文件会增加文件大小。如果未经压缩或优化&#xff0c;这些文件可能会占用较大的存储空间&#xff1b;② 动画和特效&#xff…

【Unity3D编辑器开发】Unity3D中制作一个可以随时查看键盘对应KeyCode值面板,方便开发

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在开发中&#xff0c;会遇到要使用监控键盘输入的KeyCode值来执…

十七、C语言内存函数

1 memcpy函数的使用和模拟实现 //memcpy函数的声明 void* memcpy(void* destination, const void* source, size_t num);memcpy函数可以给内存进行拷贝&#xff0c;由于不知道要拷贝的内存中存放的是哪一种类型的数据&#xff0c;所以memcpy函数的返回类型设置成了void*。 me…

【2023全网最全最火】Selenium WebDriver教程(建议收藏)

在本教程中&#xff0c;我将向您介绍 Selenium Webdriver&#xff0c;它是当今市场上使用最广泛的自动化测试框架。它是开源的&#xff0c;可与所有著名的编程语言&#xff08;如Java、Python、C&#xff03;、Ruby、Perl等&#xff09;一起使用&#xff0c;以实现浏览器活动的…

如何使用jest

最近在研究单元测试&#xff0c;虽说前端如果不是大且的项目不必要加&#xff0c;但至少得会&#xff0c;因此花了些时间研究&#xff0c;以下是我总结jest的使用。 jest是什么&#xff1f; Jest是 Facebook 的一套开源的 JavaScript 测试框架&#xff0c; 它自动集成了断言、…

bert入门

bert是什么 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是一种自然语言处理&#xff08;NLP&#xff09;中的预训练模型&#xff0c;它是基于Transformer架构的一种深度学习模型。BERT的主要目标是在大规模文本语料库上进行预训练&a…

自动求导,计算图示意图及pytorch实现

pytorch实现 x1 torch.tensor(3.0, requires_gradTrue) y1 torch.tensor(2.0, requires_gradTrue) a x1 ** 2 b 3 * a c b * y1 c.backward() print(x1.grad) print(y1.grad) print(x1.grad 6 * x1 * y1) print(y1.grad 3 * (x1 ** 2))输出为&#xff1a; tensor(36.) …

uniapp-vue3-弹出选择组件wo-pop-selector

wo-pop-selector弹出选择组件采用uniapp-vue3实现, 支持H5、微信小程序&#xff08;其他小程序未测试过&#xff0c;可自行尝试&#xff09; 可到插件市场下载尝试&#xff1a; https://ext.dcloud.net.cn/plugin?id14879 使用示例 <template><view><view c…

GBU808-ASEMI小功率开关电源GBU808

编辑&#xff1a;ll GBU808-ASEMI小功率开关电源GBU808 型号&#xff1a;GBU808 品牌&#xff1a;ASEMI 芯片个数&#xff1a;4 封装&#xff1a;GBU-4 恢复时间&#xff1a;&#xff1e;50ns 工作温度&#xff1a;-55C~150C 浪涌电流&#xff1a;200A 正向电流&#…

微信小程序报错request:fail -2:net::ERR_FAILED(生成中间证书)

微信小程序报错request:fail -2:net::ERR_FAILED-生成中间证书 前言一、检查网站ssl证书二、生成证书方法1.获取中间证书手动合并1.进入网站&#xff1a;[https://www.myssl.cn/tools/downloadchain.html](https://www.myssl.cn/tools/downloadchain.html)2.点击下一步3.手动合…

【Vue面试题十四】、说说你对vue的mixin的理解,有什么应用场景?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;说说你对vue的mixin的理…

abap代码优化和性能调优工具

select/end select与loop类似是循环&#xff08;一个是对数据库表&#xff0c;一个是对内表&#xff09; select *效率低于select 字段1 字段2... select 主键1 主键2 主键3 非主键4效率高于select 主键1 主键2 非主键4. into table 内表效率高于into corresponding fields …

Linux动态链接库.so文件

一、动态库和静态库的区别 库是一个二进制文件&#xff0c;包含的代码可以被程序调用&#xff0c;如标准库、线程库。Windows 和 Linux下的库文件格式不兼容。 Windows环境&#xff1a;静态库是 .lib 文件&#xff0c;共享库是 .dll 文件 Linux环境&#xff1a;静态库是 .a 文…

IC工程师职场必备《经典Verilog100多个代码案例》(附下载)

对于IC行业的人员而言&#xff0c;Verilog是最基础的入门&#xff0c;用于数字电路的系统设计&#xff0c;很多的岗位都会用到&#xff0c;可对算法级、门级、开关级等多种抽象设计层次进行建模。 Verilog由于其简单的语法&#xff0c;和C语言的相似性&#xff0c;目前被各大公…

uni-app:js时间与时间戳之间的转换

运行结果 代码 <template><view></view> </template><script>export default {data() {return {}},onLoad() {//时间转换为时间戳&#xff08;十位时间戳即秒级时间戳&#xff09;const time 2023-10-01 12:34:56; // 时间格式为年-月-日 时:分…

BlowFish加解密原理与代码实现

BlowFish加解密原理与代码实现 一丶简介 ​ BlowFish 是一个对称加密的加密算法。由Bruce Schneier&#xff0c;1993年设计的。是一个免费自由使用的加密算法。 了解的必要知识 BlowFish是一个对称区块加密算法。每次加密数据为 64位 &#xff08;2个int)类型数据大小。八个…

Maven 引入外部依赖

如果我们需要引入第三方库文件到项目&#xff0c;该怎么操作呢&#xff1f; pom.xml 的 dependencies 列表列出了我们的项目需要构建的所有外部依赖项。 要添加依赖项&#xff0c;我们一般是先在 src 文件夹下添加 lib 文件夹&#xff0c;然后将你工程需要的 jar 文件复制到 …

mac(M1)卸载miniconda3

参考https://stackoverflow.com/questions/29596350/how-to-uninstall-mini-conda-python step1 因为我目前只有一个base环境&#xff0c;所以直接在这个环境中安装 anaconda-clean即可 conda install anaconda-clean然后继续输入 anaconda-clean如果不加–yes&#xff0c;那…

精品Python考务监考管理系统

《[含文档PPT源码等]精品Python考务管理系统的设计与实现》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等&#xff01; 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;python 使用框架&#xff1a;Django 前端技术&#xff1a;JavaSc…

SECS/GEM封装库RapidSecs开发手记HMSM

四. SECS/GEM封装库RapidSecs开发手记-基础库开发-1 https://blog.csdn.net/jxb_memory/article/details/105739410 secsgem https://www.cnpython.com/pypi/secsgem