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

C++初学者指南-3.自定义类型(第一部分)-基本自定义类型/类

C++初学者指南-3.自定义类型(第一部分)-基本自定义类型/类

文章目录

  • C++初学者指南-3.自定义类型(第一部分)-基本自定义类型/类
    • 1.类型种类(简化)
    • 2.为什么选择自定义类型?
      • 单向计数器
      • 提升序列
    • 3.限制成员访问
      • 成员函数
      • 公共(public) vs. 私有(private)的可见性
      • const成员函数
      • 成员声明 vs. 定义
      • 操作符成员函数
    • 3.初始化
      • 成员初始化
      • 构造函数
      • 默认构造函数与自定义构造函数
      • 显式构造函数 ↔ 隐式转换
      • 构造函数委托
      • 最令人困扰的解析
    • 4.设计,约定和风格
      • 接口中的数据类型
      • 成员和非成员
      • 避免使用Setter/Getter对!
      • 命名
      • 使用专用类型!
    • 5.示例实现
      • 示例1:单向的计数器
      • 示例2:递增序列

1.类型种类(简化)

基本类型void, bool, char, int, double, …
简单聚合主要目的:数据分组
聚合:可能包含一个或多个基本类型或其他兼容的聚合类型
无法控制组成类型的相互作用。
简单,如果只有(编译器生成)默认构造函数/析构函数/拷贝构造函数/赋值函数
标准的内存布局(所有成员按声明顺序连续排列),如果所有成员都具有相同的访问控制(例如全部是公共的)
更复杂自定义类型主要目的:确保正确性和安全性保证。
自定义不变量和对成员相互作用的控制。
限制成员访问。
成员函数
用户定义的构造函数/成员初始化。
用户自定义析构函数/拷贝构造函数/赋值函数。
可以是多态的(包含虚成员函数)。

2.为什么选择自定义类型?

正确性保证

  • 不变量 = 从不改变的行为和/或数据属性
  • 通过控制/限制对数据成员的访问来避免数据损坏
  • 使用专用类型来限制函数的输入/输出值

可复用的抽象

  • 隐藏低级实现细节的易于使用的接口
  • 不受内部实现变化影响的稳定接口
  • 可重用的常用功能的抽象(例如,动态数组)

资源管理
也被称为 RAII(资源获取即初始化)

  • 在构造对象时获取一些资源(内存、文件句柄、连接等)
  • 当对象被销毁时释放/清理资源(释放内存、关闭连接等)

单向计数器

  • 存储整数
  • 初始化为0
  • 不变性:计数只能增加(不能减少或重置)
monotonous_counter c;   
cout << c.reading();  // prints 0
c.increment();
cout << c.reading();  // prints 1
c.increment();
c.increment();
cout << c.reading();  // prints 3

简单的聚合类型不能保证:

struct frail_counter {int count;
};
frail_counter c;    
cout << c.count; // any value
c.count++;
c.count = 11;
  • 整数成员未自动初始化为 0
  • 可以自由修改聚合类型的任何整数成员
  • ⇒仅使用整数没有任何优势

提升序列

  • 应该存储整数
  • 不变性:元素数量只能增加,即只能插入新元素,而不能移除它们
  • 不变性:元素必须始终按升序排序
    在这里插入图片描述
    简单的聚合不能保证:
struct chaotic_sequence {std::vector<int> nums;
};
chaotic_sequence s;     
s.nums.push_back(8);   8
s.nums.push_back(1);   8  1
s.nums.push_back(4);   8  1  4
s.nums.pop_back(4);    8  1 

可能违反要求

  • 数字不一定按升序排序
  • 我们可以随意操作数字,比如删除数字等
  • 与使用普通std::vector相比没有什么优势

3.限制成员访问

成员函数

class monotonous_counter {int count_;  // ← 数据成员
…void increment () {  // ← 成员函数++count_; }
};
class ascending_sequence {std::vector<int> seq_;  // ← 数据成员
…void insert (int x) {   // ← 成员变量// 在正确的位置将 x 插入到 nums 中}
};

成员函数可用于

  • 操作或查询数据成员
  • 控制/限制对数据成员的访问
  • 隐藏低级实现细节
  • 确保正确性:保持/保证不变量
  • 确保清晰度:为不同类型的用户设计良好结构的接口
  • 确保稳定性:内部数据表示(大部分)独立于接口
  • 避免重复/模板:避免重复/样板:对于潜在的复杂操作,只需调用一次即可

公共(public) vs. 私有(private)的可见性

私有成员只能通过成员函数访问:

class ascending_sequence {
private:std::vector<int> seq_;// … more private members
public:void insert (int x) {}auto size () const { return seq_.size(); }// … more public members
};
int main () {ascending_sequence s;s.insert(8);         //  'insert' 是公共的auto n = s.size();   //  'size' 是公共的auto i = s.seq_[0];  //  编译错误: 'seq_' 是私有的auto m = s.seq_.size(); //  编译错误s.seq_.push_back(1);    //  编译错误
}

struct 与 class – 主要区别在于默认可见性:
在这里插入图片描述

关键字通常用于
struct公共数据的简单聚合
class私有数据、成员函数、不变量……

const成员函数

只有带 const 修饰的成员函数才能被 const 对象调用:

class ascending_sequence {std::vector<int> seq_;
public:void insert {}auto size () const { return seq_.size(); }
};
int main () {ascending_sequence s;s.insert(88);  //  s不是const的auto const& cs = s; cs.insert(5);  //  编译错误: 'insert' 不是const的
}

接受常量(引用)参数的函数不仅承诺不修改它,这个承诺还将被编译器检查并强制执行。

void foo (ascending_sequence const& s) {// 's' is const reference ^^^^^auto n = s.size();  //  'size' 是 consts.insert(5);  //  编译错误: 'insert' 不是 const
}

const成员函数内部的成员是const

class monotonous_counter {int count_;
public:int reading () const { //  编译错误: count_ 是 const:count_ += 2;return count_;}
};
class ascending_sequence {std::vector<int> seq_;
public:auto size () const {  // 'seq_' 是 const//  编译错误: 调用非const的'push_back'seq_.push_back(0);  //  vector的成员 'size()' 是const的return seq_.size();  }
};

成员函数可以通过const进行重载
如果一个成员函数是const-限定的,另一个不是,它们可以有相同的名称(和参数列表)。这样可以清楚地区分只读访问和读写操作。

class interpolation {int t_;public:// 读/写函数对:void threshold (int t)  { if (t > 0) t_ = t; }int  threshold () const { return t_; }// 可写访问一个'node'node& at (int x) {}// 只读访问一个'node'node const& at (int x) const {}
};

成员声明 vs. 定义

class MyType {int n_;// 更多的成员 …
public:// 声明 + 内联定义int count () const { return n_; } // 只声明double foo (int, int);
};
// 独立定义
double MyType::foo (int x, int y) {// lots of stuff …
}
  • 通常复杂的成员函数的定义会放在类外面(放到单独的源文件中)。
  • 然而,像接口适配器函数、获取器(如 count)这样的小成员函数应该嵌入实现,即直接在类体中,以达到最佳性能。
  • 暂时我们会将所有成员函数保持内联,直到我们了解有关分离编译的知识。

操作符成员函数

特殊成员函数

class X { …Y operator [] (int i) { … } 
};

使用下标运算符。

X x;
Y y = x[0];

在这里插入图片描述

3.初始化

成员初始化

1.成员初始化器 (C++11)

class counter {// counter 应该从0开始int count_ = 0;
public:…
};
class Foo {int i_ = 10;double x_ = 3.14;
public:…
};

2.构造函数初始化列表
构造函数(ctor) = 创建对象时执行的特殊成员函数

class counter {int count_;
public:counter(): count_{0} { }…
};
class Foo {int i_;     // 1stdouble x_;  // 2nd
public:    Foo(): i_{10}, x_{3.14} { }// same order: i_ , x_ …
};

提示:确保初始化列表中的成员顺序始终是与成员声明顺序相同!

构造函数

构造函数(ctor) = 创建对象时执行的特殊成员函数

  • 构造函数的 函数名称 = 类名称
  • 没有返回类型
  • 可以通过初始化列表初始化数据成员
  • 可以在第一次使用对象之前执行代码
  • 可用于建立不变量
  • 默认构造函数 = 不带参数的构造函数
    在这里插入图片描述
    构造函数的独立定义
    与其他成员函数的方式相同
class MyType { …
public:MyType ();  // 声明…
};
// 独立定义
MyType::MyType (): … { … }

注意:确保初始化列表中的成员顺序始终是 与成员声明顺序相同!

  • 初始化列表中的不同顺序可能会导致未定义的行为,例如访问未初始化的内存。
  • 这里,在默认构造函数中,我们需要确保只有在min_和max_被初始化之后才能访问v_{min_,max_}。
  • 有些编译器会对此发出警告:例如 g++/clang++ 使用 -Wall 或 -Wreorder 选项,这就是为什么要始终启用并且决不忽略编译器警告的另一个原因!

默认构造函数与自定义构造函数

没有用户定义的构造函数⇒编译器生成一个

class BoringType { public: int i = 0; };
BoringType obj1;     // 正确
BoringType obj2 {};  // 正确

至少有一个特殊构造函数
⇒ 编译器不生成默认构造函数

class SomeType {public:// special constructor:explicit SomeType (int x){}
};
SomeType s1 {1};  //  特殊 (int) 构造函数
SomeType s2;      //  编译错误: 没有默认构造函数!
SomeType s3 {};   //  编译错误: 没有默认构造函数!

TypeName() = default;
⇒ 编译器生成默认构造函数的实现(编译器实现没有参数的构造函数就是默认构造函数)

显式构造函数 ↔ 隐式转换

// 函数有一个 'Counter' 参数
void foo (Counter c) { … }
void bar (Counter const& c) { … }

隐式转换(不好的方式)

class Counter {int count_ = 0;
public:Counter (int initial):count_{initial} {}};
// 从‘2‘创建了'Counter'对象
foo(2);           // 正确
bar(2);           // 正确
foo(Counter{2});  // 正确
bar(Counter{2});  // 正确

显式构造函数(推荐的方式)

class Counter {int count_ = 0;
public:explicitCounter (int initial):count_{initial} {}};
// 没有隐式转换: 
foo(2);  //  编译错误
bar(2);  //  编译错误
foo(Counter{2});  // 正确
bar(Counter{2});  // 正确

注意:默认情况下,让用户定义的构造函数显式!

  • 隐式转换是难以发现的错误的主要来源!
  • 只有在绝对必要且含义明确时,才使用非显式构造函数,如果需要直接从参数类型进行转换。
  • 一些较老的教材和使用 C++98 的人可能会告诉你,只需要关心单参数构造函数的隐式转换。然而自C++11以来,情况已经改变,因为现在你也可以从花括号括起的值列表中隐式地构造对象。

构造函数委托

= 调用初始化列表中的其他构造函数

class Range {int a_;int b_;
public:// 1) 特殊构造函数explicit Range (int a, int b): a_{a}, b_{b} {if (b_ > a_) std::swap(a_,b_);}// 2) 特殊[a,a]构造 - 委托给[a,b]构造函数explicit Range (int a): Range{a,a} {}// 3) default constructor - delegates to [a,a] ctorRange (): Range{0} {}};
Range r1;        // 3) ⇒ r1.a_: 0  r1.b_: 0
Range r2 {3};    // 2) ⇒ r2.a_: 3  r2.b_: 3
Range r3 {4,9};  // 1) ⇒ r3.a_: 4  r3.b_: 9
Range r4 {8,2};  // 1) ⇒ r4.a_: 2  r4.b_: 8

最令人困扰的解析

由于C++语法中的歧义,无法使用空括号进行对象构造:

class A { … };
A a ();  // 声明了没有参数和返回值的函数'a'
A a;     // 构造一个A类型对象
A a {};  // 构造一个A类型对象

4.设计,约定和风格

每种类型都应该有一个目的

  • 因为这样可以减少将来对它的修改可能性。
  • 降低出现新错误的风险
  • 根据您的类型保持代码更加稳定

保持数据成员私有并使用成员函数访问/修改数据

  • 这样用户只能通过稳定的接口与您的类型进行交互。
  • 避免数据损坏 / 允许不变量保证。
  • 如果你改变了类型的内部实现,类型的用户不需要改变他们的代码。

const - 限定所有非修改成员函数

  • 为了清楚地表明对象的内部状态如何以及何时发生改变。
  • 使您更难错误地使用您的类型。
  • 启用编译器可变性检查。
  • 更好地推理正确性,特别是在涉及同时访问对象的情况下,例如来自多个线程。
接口应该易于正确使用,并且难以错误使用。—  Scott Meyers

函数或类型的用户不应该对其目的、参数的意义、先决条件/后置条件和副作用感到困惑。

接口中的数据类型

#include <cstdint>
#include <numeric_limits>
class monotonous_counter {
public:// 公共类型别名using value_type = std::uint64_t;
private:value_type count_ = 0;
public:value_type reading () const { return count_; }…
};
const auto max = std::numeric_limits<monotonous_counter::value_type>::max();

不要泄露实现细节:

  • 只有当别名类型在您的类的公共接口中使用时,即作为公共成员函数的返回类型或参数时,才将类型别名公开。
  • 如果别名类型只在私有成员函数中使用或用于私有数据成员,请不要将类型别名公开。

成员和非成员

如何实现一个特性/添加新功能?

  • 只需要访问公共数据(例如通过成员函数访问)⇒ 实现为独立函数
  • 需要访问私有数据⇒作为成员函数实现

示例:间隔类型 gap类
如何实现一个函数,使新的间隔对象的两个边界都移动相同的量?

class gap {int a_; int b_;
public:explicit gap (int a, int b): a_{a}, b_{b} {}int a () const { return a_; }int b () const { return b_; }
};

推荐的独立式函数实现

gap shifted (gap const& g, int x) {return gap{g.a()+x, g.b()+x};
}
  • 实现仅依赖于gap的公共接口
  • 我们没有更改类型 gap 本身 ⇒ 依赖它的其他代码不需要重新编译

不推荐的成员函数实现

class gap { …gap shifted (int x) const {return gap{a_+x, b_+x};}
};
  • gap的其他用户可能想要一个具有不同语义的移位函数,但他们现在只能使用我们的函数了。
  • 所有其他代码(取决于 gap)都需要重新编译。

避免使用Setter/Getter对!

  • 使用动作/动词函数而不是仅仅使用设置器(Setter)。
  • 通常可以更好地对问题进行建模。
  • 更精细的控制。
  • 更好的代码可读性/意图表达。

推荐的描述性操作:

class Account { …void deposit (Money const&);Money try_withdraw (Money const&);Money const& balance () const;
};

不推荐的Setter/Getter对:

class Account { …void set_balance (Money const&);Money const& balance () const;
};

命名

名称应反映类型/函数的用途
推荐的:可理解的

class IPv6_Address {…};
class ThreadPool {…};
class cuboid {…};
double volume (cuboid const&) {…}

不推荐的:太笼统了

class Manager {…};
class Starter {…};
class Pool {…};
int get_number (Pool const&) {…}

不要在类型、变量、函数、私有数据成员等名称中使用前导下划线或双下划线!

  • 以下划线开头和/或包含双下划线的名称是保留给标准库和/或编译器生成的实体的。
  • 使用具有前置下划线或双下划线的名称可能会引发未定义行为!
  • 一个常见且没有问题的约定是在私有数据成员后面加下划线。
    在这里插入图片描述

使用专用类型!

  • 限制输入参数值
  • 确保中间结果的有效性
  • 保证返回值有效性

⇒编译器作为正确性检查器,如果它能编译通过,它应该是正确的

// 明确的接口:
double volume (Cuboid const&);
// 输入保证:角度以弧度为单位
Square make_rotated (Square const&, Radians angle);
// 只接受有效数量(例如:> 0)
Gadget duplicate (Gadget const& original,  Quantity times);
// 结果保证:向量已被规范化。
UnitVector3d dominant_direction (WindField const&);
//避免混淆,使用一个好的单位库。
si::kg mass (EllipsoidShell const&, si::g_cm3 density);
bool has_cycles (DirectedGraph const&);
// 易于理解的控制流程和逻辑:
Taxon species1 = classify(image1);
Taxon species2 = classify(image2);
Taxon lca = taxonomy.lowest_common_ancestor(species1, species2);

5.示例实现

示例1:单向的计数器

  • 新计数器从 0 开始
  • 只能往上数,不能往下数。
  • 对当前计数值的只读访问
#include <iostream>   // std::cout
#include <cstdint>    // std::uint64_t
class monotonous_counter {
public:using value_type = std::uint64_t;
private:value_type count_ = 0;  // initial
public:monotonous_counter () = default;explicit monotonous_counter (value_type init) noexcept: count_{init} {}void increment () noexcept { ++count_; }[[nodiscard]] value_type reading () const noexcept { return count_; }
};
int main () {monotonous_counter c;c.increment();std::cout << c.reading();  // prints 1c.increment();c.increment();std::cout << c.reading();  // prints 3
}

运行示例

示例2:递增序列

  • 存储整数
  • 通过索引对存储元素进行只读访问
  • 只能插入新元素,但不能删除它们
  • 元素始终按升序排序
  • 只能通过公共接口修改内容

‘insert’ 操作的实现以及 ‘begin’ 和 ‘end’ 成员函数的作用在我们学习了迭代器和标准库中的算法后会变得更加清晰。

#include <iostream>   // std::cout
#include <vector>     // std::vector
#include <algorithm>  // std::lower_bound
class ascending_sequence {
public:using value_type = int;
private:using storage_t = std::vector<value_type>;storage_t seq_;
public:using size_type = storage_t::size_type;void insert (value_type x) {// use binary search to find insert positionseq_.insert(std::lower_bound(seq_.begin(), seq_.end(), x), x);}[[nodiscard]] value_type operator [] (size_type idx) const noexcept { return seq_[idx]; }[[nodiscard]] size_type size () const noexcept { return seq_.size(); }// enable range based iteration[[nodiscard]] auto begin () const noexcept { return seq_.begin(); }[[nodiscard]] auto end ()   const noexcept { return seq_.end(); }
};
int main () {ascending_sequence s;  // s.seq_:  s.insert(7);           // s.seq_: 7s.insert(2);           // s.seq_: 27s.insert(4);           // s.seq_: 247s.insert(9);           // s.seq_: 2479s.insert(5);           // s.seq_: 24579std::cout << s[3];     // prints 7for (auto x : s) {std::cout << x <<' ';  // 2 4 5 7 9}// use type aliasesascending_sequence::value_type x = 1;ascending_sequence::size_type  n = 2;
}

运行示例

附上原文地址
如果文章对您有用,请随手点个赞,谢谢!^_^

相关文章:

C++初学者指南-3.自定义类型(第一部分)-基本自定义类型/类

C初学者指南-3.自定义类型(第一部分)-基本自定义类型/类 文章目录 C初学者指南-3.自定义类型(第一部分)-基本自定义类型/类1.类型种类&#xff08;简化&#xff09;2.为什么选择自定义类型&#xff1f;单向计数器提升序列 3.限制成员访问成员函数公共(public) vs. 私有(private…...

iOS之如何创建.framework静态库

番外&#xff1a;想要查看如何创建.a静态库可前往看我iOS之如何创建.a静态库-CSDN博客这篇文章。 一、创建framework项目 创建framework工程要选择iOS --> Cocoa Touch Framework输入项目名称PrintFramework也是编译生成的framework的名称。framework的名称也可以以后在项目…...

C程序设计谭浩强第五版

程序习题 第一章1、第5题2、第6题 第三章1、第2题2、第2题3、第3题4、第4题Tips 第一章 1、第5题 编写一个C程序,运行时输出以下图形: #include <stdio.h> int main() {for (int i 0; i < 4; i) // 输出4行循环控制{for (int j 0; j < i; j) //第几行就输出几…...

石油化工厂为什么要用专业防爆手机?

防爆手机之所以必须使用专业设计的产品&#xff0c;主要是出于安全考虑&#xff0c;以防止在易燃易爆环境中因手机使用不当引发爆炸事故。以下几点详细解释了使用专业化工防爆手机的必要性&#xff1a; 本质安全设计&#xff1a;顶坚专业防爆手机采用了本质安全&#xff08;本安…...

文本生成sql模型(PipableAI/pip-sql-1.3b)

安装环境 pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 pip install transformers 代码 question "What are the email address, town and county of the customers who are of the least common gender?"sc…...

机器学习中的数学底蕴与设计模式

在说机器学习设计模式之前&#xff0c;想多说几句&#xff0c;在进入软件行业最初的10年&#xff0c;那时候耳熟能详的基本就是多线程编程&#xff0c;互斥同步锁&#xff0c;设计模式&#xff0c;OOA&#xff0c;OOP&#xff0c;常规数组&#xff0c;tree&#xff0c;图的数据…...

【Android面试八股文】性能优化相关面试题:如何查找CPU占用?

文章目录 一、 如何查找CPU的占用问题二、TraceView的使用关于TraceView和Android Studio的Profiler第一步、通过Android studio 打开`Android profiler`第二步、使用步骤第三步、技术说明第四步、CPU占用相关指标说明扩展阅读一、 如何查找CPU的占用问题 在Android开发中,如…...

面试框架一些小结

springcloud的⼯作原理 springcloud由以下⼏个核⼼组件构成&#xff1a; Eureka&#xff1a;各个服务启动时&#xff0c;Eureka Client都会将服务注册到Eureka Server&#xff0c;并且Eureka Client还可以反过来从Eureka Server拉取注册表&#xff0c; 从⽽知道其他服务在哪⾥ …...

c# 往window注册表写入数据后,未写入指定的路径

c# 往window注册表写入数据后&#xff0c;未写入指定的路径 最近在用c#开发一个往注册表写入数据的一个项目&#xff0c;发现将输入写入 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell这个路径时&#xff0c;数据并没写入到这个…...

树莓派4B_OpenCv学习笔记13:OpenCv颜色追踪_程序手动调试HSV色彩空间_检测圆

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; OpenCv颜色追踪_程序手动调试HSV色彩空间_检测灰度图中的…...

Golang | Leetcode Golang题解之第198题打家劫舍

题目&#xff1a; 题解&#xff1a; func rob(nums []int) int {if len(nums) 0 {return 0}if len(nums) 1 {return nums[0]}first : nums[0]second : max(nums[0], nums[1])for i : 2; i < len(nums); i {first, second second, max(first nums[i], second)}return se…...

基于ruoyi-app的手机短信登录(uniapp)

本篇用于记录h5的框架搭建 组件地址:短信验证码登陆&#xff0c;手机号&#xff0c;验证码倒计时 - DCloud 插件市场 调整后的表单组件代码: <template><view class"login-view"><!-- <input type"tel" confirm-type"确认"…...

机器学习环境搭建

前言 个人笔记&#xff0c;记录框架和小问题&#xff0c;没有太详细记载。。 1、Anaconda安装 下载地址&#xff1a; Free Download | Anaconda &#xff08;慢&#xff09; ​ 国内镜像&#xff1a;https://link.csdn.net/?targethttp%3A%2F%2Fitcxy.xyz%2F241.html 下载…...

2095.删除链表的中间节点

给你一个链表的头节点 head 。删除链表的中间节点 &#xff0c;并返回修改后的链表的头节点 head。 长度为 n 链表的中间节点是从头数起第 ⌊n / 2⌋ 个节点&#xff08;下标从 0 开始&#xff09;&#xff0c;其中 ⌊x⌋ 表示小于或等于 x 的最大整数。 对于 n 1、2、3、4 和…...

Qt QML 坑

Qt QML 坑 QML Listview 1、不定高item 导致item重叠 ListView {id: _cityListViewproperty var _cityArray: [{ type:"A",cityArray:[]},{ type:"B",cityArray:[]},{ type:"C",cityArray:[]},{ type:"D",cityArray:[]}]model: List…...

Chrome浏览器web调试(js调试、css调试、篡改前置)

目录 1. 打开开发者工具(Dev Tool) 2. 打开命令菜单 截图 3. 面板介绍 4. CSS调试 右键检查快速到达元素处 查找DOM数 利用面板Console查找DOM节点 内置函数查找上一个选择点击的元素 5. 调试JS代码(Javascript调试) 日志调试 选择查看日志等级 眼睛观测变量 …...

【Java】Logbook优化接口调用日志输出,优雅!

logbook 简介 很多人可能没有接触过 logbook&#xff0c;但它的确是一个很好用的日志框架。引用官网的介绍 Logbook 是一个可扩展的 Java 库&#xff0c;可以为不同的客户端和服务器端技术启用完整的请求和响应日志记录。它通过以下方式满足了特殊需求&#xff1a; 允许 Web 应…...

LabVIEW电压电流实时监测系统

开发了一种基于LabVIEW和研华&#xff08;Advantech&#xff09;数据采集卡的电压电流实时监测系统&#xff0c;通过高效的数据采集和处理&#xff0c;为工业和科研用户提供高精度、实时的电压电流监测解决方案。系统采用研华USB-4711A数据采集卡&#xff0c;结合LabVIEW编程环…...

骁龙相机拍照流程分析

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 1.deliverInputEvent 拍照点击事件处理 2.submitRequestList Camera 提交拍照请求 3.createCaptureRequest 拍照请求帧数 骁龙相机通过binder 数据传输…...

sql-语句

文章目录 SQL语句的学习sql是什么sql的内置命令sql的种类sql mode库&#xff0c;表属性介绍&#xff1a;字符集&#xff0c;存储引擎列的数据类型&#xff1a;数字&#xff0c;字符串&#xff0c;时间列的约束DDL: 数据定义语言库表 Online DDL(ALGORITHM) *DML :数据操纵语言资…...

解决Vue3项目中跨域问题的步骤

决Vue3项目中跨域问题的步骤可以按照以下方式清晰地分点表示和归纳&#xff1a; 1. 使用代理服务器&#xff08;Proxy&#xff09; 步骤&#xff1a; 在Vue项目的根目录下找到或创建vue.config.js文件。在vue.config.js中配置devServer的proxy选项。设定需要代理的接口前缀&a…...

macos scroll direction

If there is no Trackpad option, we can change it in the Mouse option. How to Change the Scroll Direction on a Mac: 2 Ways...

Websocket实现方式二——注解方式

添加Websocket依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>根据ServerEndpoint注解注册Websocket Configuration public class AgentWsConfig …...

零基础开始学习鸿蒙开发-页面导航栏布局设计

目录 1.设定初始页(Idex.ets) 2.自定义首页组件 3.自定义发现页面组件 4.自定义设置页面组件 总结:主要是运用 了Tabs组件对导航栏进行布局&#xff0c;然后运用BottomTabBarStyle组件嵌套图标和文字&#xff0c;完成导航栏的制作。 1.设定初始页(Idex.ets) import {find}…...

【Hive中常见的优化手段----数据采集!Join 优化!Hive索引!数据倾斜!mapreduce本地模式!map和reduce数量调整!】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;今天主要和大家分享一下Hive中常见的优化手段----数据采集&#xff01;常见的Join 优化有哪几种&#xff01;什么是Hive索引&#xff01;数据怎么发生倾斜&#xff01;什么是mapreduce的本…...

【面试系列】软件工程师高频面试题及详细解答

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来&#xff1a;详细讲解AIGC的概念、核心技术、…...

Qt开发 | Qt界面布局 | 水平布局 | 竖直布局 | 栅格布局 | 分裂器布局 | setLayout使用 | 添加右键菜单 | 布局切换与布局删除重构

文章目录 一、Qt界面布局二、Qt水平布局--QHBoxLayout三、Qt竖直布局四、Qt栅格布局五、分裂器布局代码实现六、setLayout使用说明七、布局切换与布局删除重构1.如何添加右键菜单2.布局切换与布局删除重构 一、Qt界面布局 Qt的界面布局类型可分为如下几种 水平布局&#xff08;…...

LW-DETR: A Transformer Replacement to YOLO for Real-Time Detection

LW-DETR: A Transformer Replacement to YOLO for Real-Time Detection 论文链接&#xff1a;http://arxiv.org/abs/2406.03459 代码链接&#xff1a;https://github.com/Atten4Vis/LW-DETR 一、摘要 介绍了一种轻量级检测变换器LWDETR&#xff0c;它在实时物体检测方面超越…...

前端技术(二)——javasctipt 介绍

一、javascript基础 1. javascript简介 ⑴ javascript的起源 ⑵ javascript 简史 ⑶ javascript发展的时间线 ⑷ javascript的实现 ⑸ js第一个代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>…...

FireFox 编译指南2024 Windows10篇-环境准备(一)

1. 引言 在开源浏览器项目中&#xff0c;Firefox因其高性能和灵活性而备受开发者青睐。为了在本地环境中编译和定制Firefox&#xff0c;开发者需要做好充分的环境准备工作。这不仅是编译成功的基础&#xff0c;也是后续调试、优化和二次开发的关键步骤。 编译Firefox是一个复…...

Spring Boot中的热部署配置

Spring Boot中的热部署配置 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何在Spring Boot项目中实现热部署配置&#xff0c;提升开发效率和项…...

用ChatGPT快速打造一个专业WordPress网站

作为一个使用HostEase多年的老用户&#xff0c;我想和大家分享一下如何利用HostEase和ChatGPT快速构建一个WordPress网站的经验。这不仅仅是一个简单的操作步骤&#xff0c;更是一次从零到有的实战经历。希望我的分享能给你们带来一些实用的帮助。 获取主机服务和域名 首先&a…...

dsp入门

安装环境 安装 ccs5.5安装 BIOS-MCSDK 多核软件开发包安装 仿真器驱动 工程创建与导入工程 创建工程 创建工程填信息添加.cmd文件&#xff0c;配置内存编译 导入工程 导入 配置工程 选择properties 环境变量 头文件 库文件 仿真器 添加仿真器 先调出仿真器界面创建仿…...

Java并发编程-Atomiclnteger、LongAdder等原子类的使用及案例实战

文章目录 i++和Atomiclnteger之间的差别分析以及使用介绍i++AtomicInteger使用介绍i++ 示例AtomicInteger 示例总结Atomiclnteger中的CAS无锁化原理和思路介绍CAS 原理AtomicInteger 的 CAS 应用无锁化思路Atomiclnteger源码剖析:仅限JDK内部使用的Unsafe类`Unsafe` 类的关键作…...

九浅一深Jemalloc5.3.0 -- ②浅*size class

目前市面上有不少分析Jemalloc老版本的博文&#xff0c;但5.3.0却少之又少。而且5.3.0的架构与之前的版本也有较大不同&#xff0c;本着“与时俱进”、“由浅入深”的宗旨&#xff0c;我将逐步分析Jemalloc5.3.0的实现。 另外&#xff0c;单讲实现代码是极其枯燥的&#xff0c;…...

JavaScript——属性的增删改查

目录 任务描述 相关知识 属性的获取 方式一 方式二 属性的修改与新增 删除属性 编程要求 任务描述 Luma Restaurant 以前的财务人员在统计销售额的时候不小心把数据弄错了&#xff0c;现在的财务人员想通过一个 JavaScript 函数方便的修改数据&#xff0c;并署上自己的…...

51单片机第15步_串口多机通讯使用CRC8校验

本章重点介绍串口多机通讯使用CRC8校验。 数据格式:"$123xxxx*crc8\r\n"; 如:"$1234567890ABCDEF*06\r\n" 如:"$1231234567890*31\r\n" crc8是CRC校验值,为十六进制的ASCII码,不包含$和校验值前面的那个* #include <REG51.h> //包含…...

WPF----进度条ProgressBar(渐变色)

ProgressBar 是一种用于指示进程或任务的进度的控件&#xff0c;通常在图形用户界面&#xff08;GUI&#xff09;中使用。它提供了一种视觉反馈&#xff0c;显示任务的完成程度&#xff0c;帮助用户了解任务的进展情况。 基本特性 Minimum 和 Maximum 属性&#xff1a; 这些属…...

Apipost接口测试工具的原理及应用详解(四)

本系列文章简介&#xff1a; 随着软件行业的快速发展&#xff0c;API&#xff08;应用程序编程接口&#xff09;作为不同软件组件之间通信的桥梁&#xff0c;其重要性日益凸显。API的质量直接关系到软件系统的稳定性、性能和用户体验。因此&#xff0c;对API进行严格的测试成为…...

【图论】200. 岛屿问题

200. 岛屿问题 难度&#xff1a;中等 力扣地址&#xff1a;https://leetcode.cn/studyplan/top-100-liked/ 问题描述 给你一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&…...

AI学习指南机器学习篇-随机森林的优缺点

AI学习指南机器学习篇-随机森林的优缺点 引言 机器学习是人工智能领域的重要分支&#xff0c;其中随机森林(Random Forest)算法以其高性能和广泛应用而备受瞩目。然而&#xff0c;就像任何其他算法一样&#xff0c;随机森林也有其优缺点。本文将深入探讨随机森林算法的优势和…...

基于boost::beast的http服务器(上)

文章目录 1.beast网落库介绍2.相关类及api3.异步读写的处理3.1异步写案例3.2异步读案例 1.beast网落库介绍 Beast网络库是一个基于Boost库的C网络库&#xff0c;特别用于开发高性能的网络应用程序。它提供了一组易于使用的API&#xff0c;主要用于处理HTTP和WebSocket协议&…...

深度学习之近端策略优化(Proximal Policy Optimization,PPO)

PPO(Proximal Policy Optimization,近端策略优化)是深度强化学习中的一种算法,属于策略梯度方法中的一种。PPO通过优化策略来最大化累积奖励,具有稳定性好、易于调参等优点,是目前广泛应用的一种深度强化学习算法。下面介绍PPO的基本原理和流程。 PPO基本原理 PPO算法的…...

用pycharm进行python爬虫的步骤

使用 pycharm 进行 python 爬虫的步骤&#xff1a;下载并安装 pycharm。创建一个新项目。安装 requests 和 beautifulsoup 库。编写爬虫脚本&#xff0c;包括获取页面内容、解析 html 和提取数据的代码。运行爬虫脚本。保存和处理提取到的数据。 用 PyCharm 进行 Python 爬虫的…...

重写功能 rewrite

Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求&#xff0c;此功能依靠 PCRE(perl compatible regular expression)&#xff0c;因此编译之前要安装PCRE库&#xff0c;rewrite是nginx服务器的重要功能之 一&#xff0c;用于实现URL的重写&#xff0c;URL的…...

ISO19110操作要求类中/req/operation/operation-attributes的详细解释

/req/operation/operation-attributes 要求: 只有要素属性&#xff08;feature attributes&#xff09;可以通过‘observesValueOf’、‘triggeredByValuesOf’或‘affectsValuesOf’关联角色与要素操作&#xff08;feature operations&#xff09;关联。 具体解释 定义 要…...

访客(UV)、点击量(PV)、IP、访问量(VV)概念

1、https://www.cnblogs.com/QingPingZm/articles/13855808.htmlhttps://www.cnblogs.com/QingPingZm/articles/13855808.html...

C++系统编程篇——Linux第一个小程序--进度条

&#xff08;1&#xff09;先引入一个概念&#xff1a;行缓冲区 \r和\n \r表示回车 \n表示回车并换行 ①代码一 #include<stdio.h> #include<unistd.h> int main()…...

一个中文和越南语双语版本的助贷平台开源源码

一个中文和越南语双语版本的助贷平台开源源码。后台试nodejs。 后台 代理 前端均为vue源码&#xff0c;前端有中文和越南语。 前端ui黄色大气&#xff0c;逻辑操作简单&#xff0c;注册可对接国际短信&#xff0c;可不对接。 用户注册进去填写资料&#xff0c;后台审批&…...

【游戏引擎之路】登神长阶(五)

5月20日-6月4日&#xff1a;攻克2D物理引擎。 6月4日-6月13日&#xff1a;攻克《3D数学基础》。 6月13日-6月20日&#xff1a;攻克《3D图形教程》。 6月21日-6月22日&#xff1a;攻克《Raycasting游戏教程》。 6月23日-6月30日&#xff1a;攻克《Windows游戏编程大师技巧》。 …...

mybatisplus多条件对象xml分页查询

不要用它自带的 selectPage方法&#xff0c;会有传参问题 controller import java.util.Set;RestController RequiredArgsConstructor RequestMapping("/deviceInfo" ) public class DeviceInfoController {private final DeviceInfoService deviceInfoService;/**…...

Java中MD5加密算法的原理与实现详解

Java中MD5加密算法的原理与实现详解 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; MD5&#xff08;Message Digest Algorithm 5&#xff09;是一种广泛使用的…...

IPython脚本加载秘籍:探索脚本魔法的艺术

IPython脚本加载秘籍&#xff1a;探索脚本魔法的艺术 IPython&#xff0c;这个强大的交互式Python解释器&#xff0c;不仅提供了丰富的交互式编程功能&#xff0c;还允许用户加载和运行Python脚本。这一功能极大地扩展了IPython的实用性&#xff0c;使得用户可以在IPython环境…...

vue根据文字长短展示跑马灯效果

介绍 为大家介绍一个我编写的vue组件 auto-marquee &#xff0c;他可以根据要展示文本是否超出展示区域&#xff0c;来判断是否使用跑马灯效果&#xff0c;效果图如下所示 假设要展示区域的宽度为500px&#xff0c;当要展示文本的长度小于500px时&#xff0c;只会展示文本&…...

Python中的爬虫实战:百度知道爬虫

python作为一种强大的编程语言&#xff0c;可以帮助我们更便捷地获取互联网上的大量数据。其中&#xff0c;爬虫技术是极具代表性的一部分。爬虫可以在互联网上获取各种数据并进行分析&#xff0c;为我们提供大量的有价值的信息。在python中&#xff0c;爬虫技术也能够得到广泛…...

新版MinIO安装,附带问题处理和SSL设置(巨详细)

前些天发现了一个人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;最重要的屌图甚多&#xff0c;忍不住分享一下给大家。点击跳转到网站。 下面开始&#xff1a; 前往官网下载需要的二进制文件 wget https://dl.min.io/server/minio/release/linux-am…...

24万落地,德系标杆SUV上新,标配丰富,诚意不输国产!

5月30日晚,上汽大众途观L Pro正式上市,全系共推出6款车型,售价23.68-26.68万元。新车采用全新外观设计,并且在智能化方面进行了升级,为了更好满足中国消费者需求,途观L Pro提供了部分中国消费者独享配置,并且与国内例如科大讯飞、大疆车载等企业合作,提供更适合中国消费…...

华为举办鸿蒙生态春季沟通会,多款产品焕新亮相

2024年4月11日,华为举办鸿蒙生态春季沟通会,带来鸿蒙智行首款智慧轿车智界S7、全新华为MateBook X Pro领衔的多项新产品、新技术,并公布鸿蒙智行生态最新成绩,展示进一步完善的华为万物互联全场景生态。鸿蒙智行,全面引领智能汽车变革全场景智慧旗舰SUV问界M9上市短短三个…...

Sylvester矩阵、子结式、辗转相除法的三者关系(第二部分)

【三者的关系】 首先&#xff0c;辗转相除法可以通过Sylvester矩阵进行&#xff0c;过程如下&#xff08;以 m 8 、 l 7 m 8、l 7 m8、l7为例子&#xff09;。 首先调整矩阵中 a a a系数到最后面几行&#xff0c;如下所示&#xff1a; S ( a 8 a 7 a 6 a 5 a 4 a 3 a 2 …...

jenkins集成

jenkins是一款广泛使用的开源持续集成&#xff08;CI&#xff09;和持续交付&#xff08;CD&#xff09;工具&#xff0c;主要用于自动化构建、测试和部署软件。以下是关于如何集成Jenkins的详细介绍&#xff1a; 安装Jenkins&#xff1a; 要安装Jenkins&#xff0c;您需要按照…...

Hotcoin Research | 市场洞察:2024年5月13日-5月19日

加密货币市场表现 目前&#xff0c;加密货币总市值为1.32万亿&#xff0c;BTC占比54.41%。 本周行情呈现震荡上行的态势&#xff0c;BTC在5月15日-16日&#xff0c;有一波大的拉升&#xff0c;周末为震荡行情。BTC现价为67125美元。 上涨的主要原因&#xff1a;美国4月CPI为3…...

python mp3转mp4工具

成品UI 安装moviepy库 pip install moviepy 转换demo from moviepy.editor import *# 创建一个颜色剪辑&#xff0c;时长与音频相同 audioclip AudioFileClip(r"C:\Users\Administrator\PycharmProjects\pythonProject44\test4\赵照 - 灯塔守望人.mp3") videoclip…...