当前位置: 首页 > news >正文

11 类型泛化

11 类型泛化

  • 1、函数模版
    • 1.1 前言
    • 1.2 函数模版
    • 1.3 隐式推断类型实参
    • 1.4 函数模板重载
    • 1.5 函数模板类型形参的默认类型(C++11标准)
  • 2、类模版
    • 2.1 类模板的成员函数延迟实例化
    • 2.2 类模板的静态成员
    • 2.3 类模板的递归实例化
    • 2.4 类模板类型形参缺省值
  • 3、类模板的扩展
    • 3.1 模板型成员变量
    • 3.2 模板型成员函数
    • 3.3 模板型成员类型
    • 3.4 类模板中成员虚函数
  • 4、模板的特殊用法
    • 4.1 数值型的类型形参
    • 4.2 模板型的类型形参
  • 5、模板的经典错误(补)
    • 5.1 模板二次编译
    • 5.2 嵌套依赖
    • 5.3 利用类型形参调用成员函数模板
    • 5.4 子类模板访问基类模板

1、函数模版

1.1 前言

首先C++为强类型语言
-优点:有很多的数据类型(基本类型、类类型)在类型安全性方面是无可比拟的
-缺点:因为数据类型的多样性,在很大程度上会给程序员编写通用代码带来麻烦
这就使得程序员需要为每一种数据类型编写完全相同或者近乎完全相同的代码,即便它们在抽象层面是一致的。

int Max(int x, int y){return x > y ? x : y;
}
double Max(double x, double y){return x > y ? x : y;
}string Max(string x, string y){return x > y ? x : y;
}
int main(){int nx = 10, ny = 11;cout << Max(nx, ny) << endl;double dx = 1.0, dy = 1.1;cout << Max(dx, dy) << endl;string sx = "1.0", sy = "1.1";cout << Max(sx, sy) << endl;...如果有其他类型的比较大小,我们需要为每一种类型编写相同的代码
}

1.2 函数模版

  • 定义语法:
template<class|typename 类型形参1,class|typename类型形参2,...>返回值类型 函数模板名(调用形参1,调用形参2,…){...}示例:
template<typename T>T Max(T x,Ty){return x y?x:y;
}

注意:可以使用任何标识符作为类型形参的名称,但使用“T”己经称为一种惯例,“T”表示的是,调用者在使用函数模板时指定的任意类型

  • 使用:使用函数模板必须对函数模板进行实例化
    • 语法
函数模板名<类型实参1,类型实参2,>(调用实参1…);
  • 示例
// 定义函数模板
template<typename T>T Min(T x, T y){return x > y ? y : x;
}int main(){int nx = 10, ny = 11;// 使用函数模板cout << Min<int>(nx, ny) << endl;double dx = 1.0, dy = 1.1;cout << Min<double>(dx, dy) << endl;string sx = "1.0", sy = "1.1";cout << Min<string>(sx, sy) << endl;return 0;
}
  • 分析
    • 编译器并没有把函数模板翻译成一个可以处理任何数据类型的单一实体
    • 编译器在实例化函数模板时根据类型实参从函数模板中产生一个真正的函数实体
    • 函数模板并不是一个函数实体,通过实例化才能产生真正的函数实体
    • 函数模板可以看成是编译器生成函数实体的一个依据而已
    • 这种用具体数据类型替换函数模板类型形参的过程叫做实例化,这个过程将产生一个函数模板的实例(函数实体)
    • 原则上来说可以使用任何类型来实例化函数模板,不管其为基本类型还是类类型但前提是这个类型必须支持函数模板所要执行的操作

1.3 隐式推断类型实参

  • 概念
    • 若函数模板的调用形参和类型形参相关,那么在实例化函数模板时即使不显式指明类型实参,编译器也有能力根据调用实参的类型隐式推断出类型实参的类型
    • 获得和调用普通函数一致的书写形式
template<typename T>T Min(T x, T y){return x > y ? y : x;
}
int main(){int nx = 10, ny = 11;// 调用形参和类型形参相关cout << Min(nx, ny) << endl;// --> cout << Min<int>(nx, ny) << endl;double dx = 1.0, dy = 1.1;cout << Min(dx, dy) << endl;string sx = "1.0", sy = "1.1";cout << Min(sx, sy) << endl;return 0;
}
  • 三种情况不能做隐式推断
    1: 调用参数和类型参数不完全相关
template  <typename T, typename D>void Foo(D x){cout << x << endl;
}
int main(){int nx = 10, ny = 11;//Foo(nx);// 不能推断出T的类型Foo<float>(nx);return 0;
}

2: 隐式推断类型实参不能同时隐式类型转换

template  <typename T>void Foo1(T x,T y){cout << x << endl;
}
int main(){// Foo1(11,13.5);// 隐式推断类型实参不能同时隐式类型转换Foo1(11, (int)13.5);return 0;
}

3: 返回值类型不能隐式推断

template<typename R,typename T>
R Bar(T x){R r;return t;
}
// 返回值类型不能隐式推断
void C11_06(){int a = 10;//Bar(10);// 根据实参能推断出形参T的类型,但是无法推断出R的类型Bar<float>(10); 
}

1.4 函数模板重载

  • 普通函数能够实例化出该函数的函数模板构成重载关系
    • 在调用参数类型匹配度相同情况下编译器优先选择普通函数
    • 除非函数模板可以产生调用参数类型匹配度更好的函数
  • 隐式推断类型实参不能同时隐式类型转换但普通函数可以,如果在传递参数时如果需要编译器做隐式类型转换,则编译器选择普通函数。
  • 可以在实例化时用<>强行通知编译器选择函数模板。
void MaxType(int x, int y){cout <<"1.MaxType" << endl;
}
template<typename T>void MaxType(T x, T y){cout << "2.MaxType" << endl;
}int main(){int nx = 10, ny = 11;MaxType(nx,ny); // 调用普通函数  在调用参数类型匹配度相同情况下编译器优先选择普通函数double dx = 1.0, dy = 1.1;MaxType(dx, dy);// 调用函数模版 函数模板可以产生调用参数类型匹配度更好的函数MaxType(nx,dy);// 调用函数模版 隐式推断类型实参不能同时隐式类型转换但普通函数可以MaxType<>(nx, ny);// <>强行通知编译器选择函数模板。return 0;
}

1.5 函数模板类型形参的默认类型(C++11标准)

  • 函数模板的类型形参可以带有默认类型
    • 在实例化函数模板时,如果提供了类型实参则用所提供的类型实参来实例化函数模板
    • 在实例化函数模板时,如果没提供类型实参则用类型形参的缺省类型来实例化函数模板
    • 如果某一个类型形参带有缺省类型,则其后的类型形参都必须带有缺省类型
template  <typename T=short, typename D=float>void Foo2(int x=0){T t;D d;cout << "t的类型" << typeid(t).name() << " d的类型" << typeid(d).name() << endl;
}
int main(){Foo2<int, double>(100);// 用提供的类型Foo2(100);// 用默认类型return 0;
}

2、类模版

  • 形式:
// 书写
template<tyepname类型形参1,...>
class 类模板名{...
}
// 示例
template<typename A,typename B>
class CMath{
public:A m a;B func0{…}
}
  • 使用:类模板必须对类模板进行实例化(产生真正的
    • 类模板本身并不代表一个确定的类型(即不能用于定义对象
    • 只有通过类型实参实例化成真正的类后才具备类的特性(即可以定义对象)。
template<typename T>
class CMath{
public:CMath(T t1, T t2) :m_t1(t1), m_t2(t2){}T add(){ return m_t1 + m_t2; }T sub();// 声明
private:T m_t1;T m_t2;
};
// T sub()定义 template<typename T>不能丢,要用类名引成员,切记不用要类模板引成员
template<typename T>
T CMath<T>::sub(){return m_t1 - m_t2;
}int main(){int nx = 10, ny = 11;CMath<int>m1(nx, ny);cout << m1.add() << endl;double dx = 1.0, dy = 1.1;CMath<double>m2(dx, dy);cout << m2.add() << endl;string sx = "1.0", sy = "1.1";CMath<string>m3(sx, sy);cout << m3.add() << endl;return 0;
}

2.1 类模板的成员函数延迟实例化

类模板被实例化产生真正类的一刻,类模板中的成员函数并没有实例化, 成员函数只有在被调用时才会被实例化(即产生真正成员函数),称之为成员函数的延迟实例化
注意:成员虚函数除外
某些类型虽然并没有提供类模板所需要的全部功能,但照样可以用它来实例化类模板,只要不调用那些未提供功能的成员函数即可。

int main(){// CMath<int> 编译到这是,类中只有成员变量,没有成员函数// CMath<int>m1(nx,ny) // 此时编译器才会给类中添加构造函数// m1.add()  // 此时才会去类中添加add的成员函数return 0;
}

2.2 类模板的静态成员

  • 类模板中的静态成员既不是每个对象拥有一份也不是类模板拥有一份,应该是由类模板实例化出的每一个真正的类各自拥有一份,且为该实例化类定义的所有对象共享
template <typename T> class A
{
public:static T m_t;// 声明static void foo(){cout << "A<T>::foo()" << endl;}
};
template <typename T> T A <T> ::m_t=T();// 定义 T()零值初始化
// 类模板中的静态成员即不是每个对象拥有一份也不是类模板拥有一份,
// 应该是由类模板实例化出的每一个真正的类各自拥有一份,且为该实例化类定义的所有对象共享
int main(){A<int> x, y;cout << "&A<int>::m_t:" << &A<int>::m_t << endl; // &A<int>::m_t:00DB53F8cout << "&x.m_t:" << &x.m_t << " &y.m_t:" << &y.m_t << endl; //&x.m_t:00DB53F8 &y.m_t:00DB53F8A<double> m, n;cout << "&A<double>::m_t:" << &A<double>::m_t << endl; // &A<double>::m_t:00DB5400cout << "&m.m_t:" << &m.m_t << " &m.m_t:" << &m.m_t << endl;// &m.m_t:00DB5400 &m.m_t:00DB5400return 0;
}

2.3 类模板的递归实例化

  • 概念
    • 利用类模板实例化产生的类来实例化类模板自身,这种做法称之为类模板的递归实例化
  • 应用
    • 通过这种方法可以构建空间上具有递归特性的数据结构
      (例如:多维数组)
  • 示例
    • Array<Array<int> >
template<typename T>class Array{
public:T& operator[](size_t i){return arr[i];}
private:T arr[10];
};
# include <iomanip>
int main(){Array<int> a; // a对象当成是一维数组看待for (int i = 0; i < 10; i++){a[i] = 1000 + i;}for (int i = 0; i < 10; i++){cout << a[i] << " ";}cout << endl;Array< Array<int> > b; // 类模板的递归实例化for (int i = 0; i < 10; i++){for (int j = 0; j < 10; j++){b[i][j] = i*j;}}for (int i = 1; i < 10; i++){for (int j = 1; j <= i; j++){cout << i << "X" << j << "=";cout << left << setw(2) << setfill(' ') << b[i][j] << " ";}cout << endl;}return 0;
}

2.4 类模板类型形参缺省值

  • 类模板的类型形参可以带有缺省类型
    • 在实例化类模板时,如果提供了类型实参则用所提供的类型实参来实例化类模板
    • 在实例化类模板时,如果没提供类型实参则用类型形参的缺省类型来实例化类模板
    • 如果某一个类型形参带有缺省类型,则其后的类型形参都必须带有缺省类型
template<typename T=short,typename D=int>
class CCMath{
private:T m_t;D m_d;
public:void print(){cout << "m_t的类型:" << typeid(m_t).name() << endl;cout << "m_d的类型:" << typeid(m_d).name() << endl;}
};int main(){CCMath<>m1;CCMath<int>m2;CCMath<int,double>m3;m1.print();m2.print();m3.print();return 0;
}

3、类模板的扩展

3.1 模板型成员变量

成员变量,但其类型是由类模板实例化的未知类,称之为模板型成员变量

  • 示例
template <typename T> class Array{...}
template <typename D> class Sum{
public :Array<D> m_d;	// 模板型成员变量
}
template<typename T>class Array2{
public:T& operator[](size_t i){return arr[i];}
private:T arr[10];
};
template<typename D>class Sum{
public:Sum(const Array2<D>& v) :m_a(v){}D add(){ // 求和器D d = D();for (int i = 0; i < 10; i++){d += m_a[i];}return d;}
private:Array2<D> m_a;//模板型成员变量
};int main(){Array2<int> a;for (int i = 0; i < 10; i++){a[i] = i+1;}Sum<int> s(a);cout << s.add() << endl;return 0;
}

3.2 模板型成员函数

模板型成员函数 又名 成员函数模板
示例:

template<typename T> class BB{
public:template<typename D>void foo(){ // 成员函数模板cout << "AA::foo<D>" << endl;}template<typename D>void bar();// 声明
};
template<typename T> template<typename D> void BB<T>::bar(){// 定义cout << "BB :: bar" << endl;
};void C11_15(){AA a;a.foo<int>();BB<int>b; // 对类模板实例化b.foo<int>();// 对函数模板实例化b.bar<int>();
}

3.3 模板型成员类型

template<typename X>class A1{
public:template<typename Y>class B1{public:template<typename X> void foo(){ // 模板型成员类型cout << "foo() " << endl;}};
};
int main(){A1<int>::B1<int>b;b.foo<int>();return 0;
}

3.4 类模板中成员虚函数

template <typename T> class Base{
public:virtual void foo(){//虚函数cout << "Base<T>::foo" << endl;}
};
// 只有在父子类中,才可以将模板进行合并
template<typename T, typename D>class Derived :public Base<T>{
public:void foo(){cout << "Derived<T,D>::foo" << endl;}
};
int main(){Derived<int, double> dr;Base<int>* pdase = &dr;pdase->foo();return 0;
}

注意:类模板中可以有虚函数,也可以表现出多态性,但是不能有成员虚函数模板
这是因为根据成员虚函数的多态机制,需要一个虚函数表(表中保存成员虚函数的入口地址),而这个表是编译器在实例化类模板时就创建,而成员函数模板的实例化(即产生真正的函数实体)需要编译器处理完并且调用后才会完成,这时才出现成员虚函数的地址,所以成员函数模板的延迟实例化,阻碍了虚函数表的构建

4、模板的特殊用法

4.1 数值型的类型形参

模板的类型形参也可以是数值类型(只能是整数),可以有缺省值

template<typename T,int S=10>class Array{
public:T& operator[](size_t i){return arr[i];}int size(){return S;}
private:T arr[S];
};
int main(){Array<int, 30> a;for (int i = 0; i < a.size(); i++){a[i] = 1000 + i;}for (int i = 0; i < a.size(); i++){cout << a[i] << ' ';}return 0;
}

4.2 模板型的类型形参

模板的类型形参也可以是类模版,可以有缺省值

template<typename T>class Array{
public:T& operator[](size_t i){return arr[i];}int size(){return 10;}
private:T arr[10];
};
template<typename D, template<typename M> class C = Array> class SumArray{
public:SumArray(const C<D>& v) :m_a(v){};D add(){D a = D();for (int i = 0; i < m_a.size(); i++){a += m_a[i];}return a;}
private:C<D> m_a;
};
int main(){Array<int> a;for (int i = 0; i < a.size(); i++){a[i] = 1000 + i;}SumArray<int, Array> s(a);cout << s.add() << endl;
}

5、模板的经典错误(补)

5.1 模板二次编译

如果都过不了第一次编译,那么就谈不上第二次编译

  • 编译器对模板会进行两次编译
  • 第一次编译:发生在实例化模板之前(产生真正函数或真正类之前)只检查模板本身内部代码(只检查基本词法是否正确)
    • 模板内部出现的所有标识符是否均有声明
    • 对于已知类型的调用要检查调用是否有效
    • 对于未知类型调用认为都合理
  • 第二次编译:第二次编译发生在实例化模板之后(产生真正函数或真正类之后)结合所使用的类型实参,再次检查模板代码,查看所有调用是否真的都有效
template<typename T>void func(){// 第一次编译时,编译器针对未知类型调用采用隐忍态度,尽量认为都合理//fdf; //错误 模板内部出现的所有标识符是否均有声明   第一次编译A3 a; a.foo(); // 对于已知类型的调用要检查调用是否有效 第一次编译//a.fdfddf();// 错误 在A3类中没有fdfddf 第一次编译T t;t.jsjhdeasde();// 第一次编译不会报错,这是因为对于未知类型调用认为都合理  ,第二次编译会报错,这是因为第二次编译时,编译器结合类型实参,再次检查,所有调用是否真的合理// t.fds<fd>fd();// 这种的第一次编译也会报错
}
int main(){func<int>();return 0;
}

5.2 嵌套依赖

  • 问题:由于模板要经过两次编译,在第一次编译模板的代码时,类型形参的具体类型尚不明确,编译器将把类型形参的嵌套类型理解为某个未知类型的静态成员变量,因此编译器看到使用这样的标识符声明变量时会报告错误,这就叫嵌套依赖。
  • 解决办法:在类型形参的前面增加一个typename标识符,意在告诉编译器其后是一个类模板的嵌套使用。
class A{
public:class B{public:void foo(){cout << "A::B::foo" << endl;}};
};
template<typename T>void func1(){
// 第一次编译时,会把T::B看做成B是T的静态成员变量,编译器看到使用这样的标识符声明变量时会报告错误
// T::B 类型形参的嵌套类型   typename 告诉编译器B是T(未知类)的嵌套类型typename T::B b;b.foo();
}
int main(){func1<A>();return 0;
}

5.3 利用类型形参调用成员函数模板

  • 问题:利用未知类定义的对象来访问成员函数模板时,编译器在第一次编译时无法解析成员函数模板的类型参数列表的<>而报告编译错误。
  • 解决方法:在成员函数模板之前增加template关键字,意在告诉编译器其后是一个函数模板实例,编译器就可以正确理解<>了。
class A{
public:template <typename T> void foo(){cout << "A::f00" << endl;}
};
template <typename T> void func2(){T t;// 编译器第一次编译时,未知类型定义的对象,调用方法时,不能带有<>    // template告诉编译器后面的是函数模板的实例化t.template foo<int>(); 
}
int main(){ func2<A>(); return 0;
}

5.4 子类模板访问基类模板

  • 问题:在子类模板中访问基类模板的成员,编译器第一次编译时只在子类模板和全局域中搜索使用的标识符号,不会到基类模板中搜索
  • 解决方法:在子类模板中可以通过使用作用域限定符或显式使用this指针
template <typename T > class BaseA{
public:int m_i;void foo(){ cout << "BaseA<T>::foo()" << endl; }
};
template<typename T, typename D> class Deri : public BaseA<T>{
public:void bar(/*    this*/ ){//m_i = 100; 报错 //foo();BaseA::foo();BaseA::m_i = 100;this->foo();this->m_i = 100;}
};
int main(){Deri<int, int >d;d.bar();return 0;
}

相关文章:

11 类型泛化

11 类型泛化 1、函数模版1.1 前言1.2 函数模版1.3 隐式推断类型实参1.4 函数模板重载1.5 函数模板类型形参的默认类型&#xff08;C11标准&#xff09; 2、类模版2.1 类模板的成员函数延迟实例化2.2 类模板的静态成员2.3 类模板的递归实例化2.4 类模板类型形参缺省值 3、类模板…...

UE4_后期_ben_模糊和锐化滤镜

学习笔记&#xff0c;不喜勿喷&#xff0c;侵权立删&#xff0c;祝愿生活越来越好&#xff01; 本篇教程主要介绍后期处理的简单模糊和锐化滤镜效果&#xff0c;学习之前首先要回顾下上节课介绍的屏幕扭曲效果&#xff1a; 这是全屏效果&#xff0c;然后又介绍了几种蒙版&#…...

Spring Boot中Excel的导入导出的实现之Apache POI框架使用教程

文章目录 前言一、Apache POI 是什么&#xff1f;二、使用 Apache POI 实现 Excel 的导入和导出① 导入 Excel1. 添加依赖2. 编写导入逻辑3. 在 Controller 中处理上传请求 ② 导出 Excel1. 添加依赖2. 编写导出逻辑3. 在 Controller 中处理导出请求 总结 前言 在 Spring Boot …...

CentOS搭建kubernetes集群详细过程(yum安装方式)

kubernetes集群搭建详细过程&#xff08;yum安装方式&#xff09; Kubernetes&#xff0c;也被称为K8s&#xff0c;是一个多功能的容器管理工具&#xff0c;它不仅能够协调和调度容器的部署&#xff0c;而且还能监控容器的健康状况并自动修复常见问题。这个平台是在谷歌十多年…...

Java 面试题:Java 的 Exception 和 Error 有什么区别?

在Java编程中&#xff0c;异常处理是确保程序稳健性和可靠性的重要机制。Java提供了一套完善的异常处理框架&#xff0c;通过捕获和处理异常&#xff0c;开发者可以有效地应对程序运行时可能出现的各种问题。在这一框架中&#xff0c;Exception和Error是两个核心概念&#xff0…...

在Vue 3中,el-select循环el-option的常见踩坑点,value值绑定对象类型?选中效果不准确?

在Vue 3中&#xff0c;el-select 组件是来自 Element Plus UI 库的一部分。 如果你想要设置默认选中的选项&#xff0c;你可以使用 v-model 来绑定选中的值。如果你想要在某个时刻让某个选项显示为已选中&#xff0c;可以设置对应的值到 v-model 绑定的数据。 <template>…...

Qt实现单例模式:Q_GLOBAL_STATIC和Q_GLOBAL_STATIC_WITH_ARGS

目录 1.引言 2.了解Q_GLOBAL_STATIC 3.了解Q_GLOBAL_STATIC_WITH_ARGS 4.实现原理 4.1.对象的创建 4.2.QGlobalStatic 4.3.宏定义实现 4.4.注意事项 5.总结 1.引言 设计模式之单例模式-CSDN博客 所谓的全局静态对象&#xff0c;大多是在单例类中所见&#xff0c;在之前…...

通过nginx转发后应用偶发502bad gateway

序言 学习了一些东西&#xff0c;如何才是真正自己能用的呢&#xff1f;好像就是看自己的潜意识的反应&#xff0c;例如解决了一个问题&#xff0c;那么下次再碰到类似的问题&#xff0c;能直接下意识的去找到对应的信息&#xff0c;从而解决&#xff0c;而不是和第一次碰到一样…...

linux中如何进行yum源的挂载

linux中如何进行yum源的挂载 ​ 1.首先创建目录[rootserver /]# mkdir /rhel92.使用mount命令进行、dev/cdrom/的镜像文件进行挂载[rootserver /]# mount /dev/cdrom /rhel9/ ​ 注意&#xff1a;此时设立的是临时命令。重启后则失效&#xff0c;若想在下次开启后仍然挂载&a…...

ffmpeg的部署踩坑及简单使用方式

ffmpeg的使用方式有以下几种: 使用原生安装包 直接在ffmpeg官网上下载安装该软件,加入到环境变量中就可以使用了 优点:简单,灵活,代码中也不用添加其他第三方的包 缺点:需要手动安装ffmpeg,这点比较麻烦 部署-windows 在windows环境下,有时就算加入到了环境变量,…...

misc刷题记录2[陇剑杯 2021]

[陇剑杯 2021]webshell (1)单位网站被黑客挂马&#xff0c;请您从流量中分析出webshell&#xff0c;进行回答&#xff1a; 黑客登录系统使用的密码是_____________。得到的flag请使用NSSCTF{}格式提交。 这里我的思路是&#xff0c;既然要选择的时间段是黑客登录网站以后&…...

AI发展面临的问题? —— AI对创造的重新定义

一、AI的问题描述 AI与数据安全问题&#xff1a;随着AI技术的发展和应用&#xff0c;数据安全问题日益突出。AI模型训练依赖于大量数据&#xff0c;而这些数据中可能包含个人隐私、商业秘密等敏感信息。如果数据在采集、存储、使用过程中处理不当&#xff0c;可能导致数据泄露或…...

k8s学习--OpenKruise详细解释以及原地升级及全链路灰度发布方案

文章目录 OpenKruise简介OpenKruise来源OpenKruise是什么&#xff1f;核心组件有什么&#xff1f;有什么特性和优势&#xff1f;适用于什么场景&#xff1f; 什么是OpenKruise的原地升级原地升级的关键特性使用原地升级的组件原地升级的工作原理 应用环境一、OpenKruise部署1.安…...

上海亚商投顾:沪指缩量调整 PCB概念股持续爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 大小指数昨日走势分化&#xff0c;沪指全天震荡调整&#xff0c;创业板指午后涨超1%。消费电子板块全天强势&a…...

QT属性系统,简单属性功能快速实现 QT属性的简单理解 属性学习如此简单 一文就能读懂QT属性 QT属性最简单的学习

4.4 属性系统 Qt 元对象系统最主要的功能是实现信号和槽机制&#xff0c;当然也有其他功能&#xff0c;就是支持属性系统。有些高级语言通过编译器的 __property 或者 [property] 等关键字实现属性系统&#xff0c;用于提供对成员变量的访问权限&#xff0c;Qt 则通过自己的元对…...

【IEEE出版丨EI检索】2024新型电力系统与电力电子国际会议(NPSPE 2024)

2024新型电力系统与电力电子国际会议&#xff08;NPSPE 2024&#xff09;将于8月16日至18日在中国大连举行&#xff0c;本届大会致力于为相关领域的专家和学者提供一个探讨行业热点问题&#xff0c;促进科技进步&#xff0c;增加科研合作的平台。本届大会涵盖新型电力系统和电力…...

【Netty】nio阻塞非阻塞Selector

阻塞VS非阻塞 阻塞 阻塞模式下&#xff0c;相关方法都会导致线程暂停。 ServerSocketChannel.accept() 会在没有建立连接的时候让线程暂停 SocketChannel.read()会在没有数据的时候让线程暂停。 阻塞的表现就是线程暂停了&#xff0c;暂停期间不会占用CPU&#xff0c;但线程…...

ES 操作

1、删除索引的所有记录 curl -X POST "localhost:9200/<index-name>/_delete_by_query" -H Content-Type: application/json -d {"query": {"match_all": {}} }POST /content_erp_nlp_help/_delete_by_query { "query": { &quo…...

uniapp如何实现跳转

在 UniApp 中&#xff0c;页面跳转主要可以通过两种方式实现&#xff1a;使用 <navigator> 组件和调用 UniApp 提供的导航 API。以下是这两种方式的详细说明&#xff1a; 1. 使用 <navigator> 组件 <navigator> 组件允许你在页面上创建一个可点击的元素&am…...

Stable-Diffusion-WebUI 常用提示词插件

SixGod提示词插件 SixGod提示词插件可以帮助用户快速生成逼真、有创意的图像。其中包含&#xff0c;清空正向提示词”和“清空负向提示词、提示词起手式包含人物、服饰、人物发型等各个维度的提示词、一键清除正面提示词与负面提示词、随机灵感关键词、提示词分类组合随机、动…...

单片机 PWM输入捕获【学习记录】

前言 学习是永无止境的&#xff0c;就算之前学过的东西再次学习一遍也能狗学习到很多东西&#xff0c;输入捕获很早之前就用过了&#xff0c;但是仅仅是照搬例程没有去进行理解。温故而知新&#xff01; 定时器 定时器简介 定时器的分类 高级定时器 通用定时器 基本定时器…...

3.1、前端异步编程(超详细手写实现Promise;实现all、race、allSettled、any;async/await的使用)

前端异步编程规范 Promise介绍手写Promise&#xff08;resolve&#xff0c;reject&#xff09;手写Promise&#xff08;then&#xff09;Promise相关 API实现allraceallSettledany async/await和Promise的关系async/await的使用 Promise介绍 Promise是一个类&#xff0c;可以翻…...

3.1. 马氏链-马氏链的定义和示例

马氏链的定义和示例 马氏链的定义和示例1. 马氏链的定义2. 马氏链的示例2.1. 随机游走2.2. 分支过程2.3. Ehrenfest chain2.4. 遗传模型2.5. M/G/1 队列 马氏链的定义和示例 1. 马氏链的定义 对于可数状态空间的马氏链, 马氏性指的是给定当前状态, 其他过去的状态与未来的预测…...

红利之外的A股底仓选择:A50

内容提要 华泰证券指出&#xff0c;当前指数层面下行风险不大&#xff0c;市场再入震荡期下&#xff0c;可关注三条配置线索&#xff1a;1&#xff09;A50为代表的产业巨头&#xff1b;2&#xff09;以家电/食饮/物流/出版为代表的稳健消费龙头&#xff0c;3&#xff09;消费电…...

wondershaper 一款限制 linux 服务器网卡级别的带宽工具

文章目录 一、关于wondershaper二、文档链接三、源码下载四、限流测试五、常见报错1. /usr/local/sbin/wondershaper: line 145: tc: command not found2. Failed to download metadata for repo ‘appstream‘: Cannot prepare internal mirrorlist: No URLs.. 一、关于wonder…...

独孤思维:盲目进群,根本赚不到钱

01 我看有些伙伴&#xff0c;对标同行找写作素材和灵感的时候。 喜欢把对标文章发给ai提炼总结。 这个方法好是好&#xff0c;但是&#xff0c;有一个问题。 即&#xff0c;无法感受全文的细节。 更无法感受作者的情感和温度。 就好像电影《记忆大师》一样。 我提取了记…...

针对indexedDB的简易封装

连接数据库 我们首先创建一个DBManager类&#xff0c;通过这个类new出来的对象管理一个数据库 具体关于indexedDB的相关内容可以看我的这篇博客 indexedDB class DBManager{}我们首先需要打开数据库&#xff0c;打开数据库需要数据库名和该数据库的版本 constructor(dbName,…...

网络编程--网络理论基础(二)

这里写目录标题 网络通信流程mac地址、ip地址arp协议交换机路由器简介子网划分网关 路由总结 为什么ip相同的主机在与同一个互联网服务通信时不冲突公网ip对于同一个路由器下的不同设备&#xff0c;虽然ip不冲突&#xff0c;但是因为都是由路由器的公网ip转发通信&#xff0c;接…...

Python MongoDB 基本操作

本文内容主要为使用Python 对Mongodb数据库的一些基本操作整理。 目录 安装类库 操作实例 引用类库 连接服务器 连接数据库 添加文档 添加单条 批量添加 查询文档 查询所有文档 查询部分文档 使用id查询 统计查询 排序 分页查询 更新文档 update_one方法 upd…...

Node.js 入门:

Node.js 是一个开源、跨平台的 JavaScript 运行时环境&#xff0c;它允许开发者在浏览器之外编写命令行工具和服务器端脚本。以下是一些关于 Node.js 的基础教程&#xff1a; 1. **Node.js 入门**&#xff1a; - 了解 Node.js 的基本概念&#xff0c;包括它是一个基于 Chro…...

宝安做棋牌网站建设哪家技术好/郑州关键词优化顾问

4.1 系统架构 自底向上分为设备层和网络层、数据操作层、图计算层、API层、应用层。 4.2 设计理念 &#xff08;1&#xff09;将图的定义和图的运行完全分开。 编程模式通常分为命令式编程和符号式编程。命令式编程是编写我们理解的通常意义上的程序&#xff0c;很容易理解和调…...

优化网站工具/seo培训机构

刚接触BarTender 2016的小伙伴们可能对条码的数据源还不太搞的定&#xff0c;例如有时需要将日期变量和序列号变量放一起打印成条码&#xff0c;那如何简单达到目的呢&#xff1f;下面&#xff0c;小编教大家解决这一问题的三大步骤。 1、在BarTender 2016中&#xff0c;选择需…...

做网站开发想转行做医药销售/51外链代发网

关联引用概念 利用 OC 语言的动态性&#xff0c;借助运行时&#xff08;runtime&#xff09;的功能&#xff0c;我们可以为已存在的实例对象增加实例变量&#xff0c;这个功能叫做关联引用。 添加、检索和断开关联 objc_setAssociatedObject(id _Nonnull object, const void * …...

郑州软件外包开发/网站优化关键词

用户二叉树排序需求用户注册&#xff0c;输入以下注册信息&#xff1a;- 电子邮箱- 密码- 确认密码- 推荐人ID(此ID可以在数据库中手动增加一个)每注册进一个新用户&#xff0c;该用户就进入到排序中排序规则新增用户必须在推荐人下面按照从左到右,从上到下的方式遍历&#xff…...

用了wordpress的网站/seo网站优化推广怎么样

两周&#xff0c;我们就犹如一个婴儿&#xff0c;从母亲的怀抱实现了能够扶墙而立的成长历程。经过两周的实践&#xff0c;我基本能按照教案的要求&#xff0c;将一堂体育课较为完整执行开展&#xff0c;而且最重要的是我们每个人从心理上实现了从学生到教师的转变&#xff0c;…...

兰州营销型网站建设/企业网络规划与设计

递归 func recursion(n:Int)->Int{if(n<1){return 1}else{return recursion(n: n-1)recursion(n: n-2)} } recursion(n: 6)效果变化图 系统自带函数 2/2 abs(-2) assert(true) max(2,3) max(12,31,23,1,41,24,1) min(12,312,312,3,213,12,312,3) //新增分隔符和结尾&a…...