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

Objects and Classes (对象和类)

Objects and Classes [对象和类]

  • 1. Procedural and Object-Oriented Programming (过程性编程和面向对象编程)
  • 2. Abstraction and Classes (抽象和类)
    • 2.1. Classes in C++ (C++ 中的类)
    • 2.2. Implementing Class Member Functions (实现类成员函数)
    • 2.3. Using Classes (使用类)
  • References

Object-oriented programming (OOP) is a particular conceptual approach to designing programs, and C++ has enhanced C with features that ease the way to applying that approach.
面向对象编程 (OOP) 是一种特殊的、设计程序的概念性方法,C++ 通过一些特性改进了 C 语言,使得应用这种方法更容易。

ease [iːz]:v. 缓解,减轻,放松,降低 n. 容易,安逸,自在,舒适

The following are the most important OOP features:

  • Abstraction (抽象)
  • Encapsulation and data hiding (封装和数据隐藏)
  • Polymorphism (多态)
  • Inheritance (继承)
  • Reusability of code (代码的可重用性)

The class is the single most important C++ enhancement for implementing these features and tying them together.
为了实现这些特性并将它们组合在一起,C++ 所做的最重要的改进是提供了类。

1. Procedural and Object-Oriented Programming (过程性编程和面向对象编程)

In short, with a procedural approach, you first concentrate on the procedures you will follow and then think about how to represent the data.
采用过程性编程方法时,首先考虑要遵循的步骤,然后考虑如何表示这些数据。

In short, with an OOP approach, you concentrate on the object as the user perceives it, thinking about the data you need to describe the object and the operations that will describe the user’s interaction with the data. After you develop a description of that interface, you move on to decide how to implement the interface and data storage. Finally, you put together a program to use your new design.
采用 OOP 方法时,首先从用户的角度考虑对象,描述对象所需的数据以及描述用户与数据交互所需的操作。完成对接口的描述后,需要确定如何实现接口和数据存储。最后,使用新的设计方案创建出程序。

perceive [pə(r)ˈsiːv]:v. 认为,意识到,注意到,察觉到

2. Abstraction and Classes (抽象和类)

Life is full of complexities, and one way we cope with complexity is to frame simplifying abstractions. From abstraction, it is a short step to the user-defined type, which in C++ is a class design that implements the abstract interface.
生活中充满复杂性,处理复杂性的方法之一是简化和抽象。抽象是通往用户定义类型的捷径,在 C++ 中,用户定义类型指的是实现抽象接口的类设计。

For built-in types, the information about operations is built in to the compiler. But when you define a user-defined type in C++, you have to provide the same kind of information yourself. In exchange for this extra work, you gain the power and flexibility to custom fit new data types to match real-world requirements.
对于内置类型来说,有关操作的信息被内置到编译器中。但在 C++ 中定义用户自定义的类型时,必须自己提供这些信息。付出这些劳动换来了根据实际需要定制新数据类型的强大功能和灵活性。

2.1. Classes in C++ (C++ 中的类)

A class is a C++ vehicle for translating an abstraction to a user-defined type. It combines data representation and methods for manipulating that data into one neat package.
类是一种将抽象转换为用户定义类型的 C++ 工具,它将数据表示和操纵数据的方法组合成一个整洁的包。

Generally, a class specification has two parts:

  • A class declaration, which describes the data component, in terms of data members, and the public interface, in terms of member functions, termed methods
    类声明:以数据成员的方式描述数据部分,以成员函数 (被称为方法) 的方式描述公有接口。

  • The class method definitions, which describe how certain class member functions are implemented
    类方法定义:描述如何实现类成员函数。

Roughly speaking, the class declaration provides a class overview, whereas the method definitions supply the details.
类声明提供了类的蓝图,而方法定义则提供了细节。

An interface is a shared framework for interactions between two systems. But in any case, to use a class, you need to know its public interface; to write a class, you need to create its public interface.
接口是一个共享框架,供两个系统交互时使用。要使用某个类,必须了解其公共接口;要编写类,必须创建其公共接口。

Typically, C++ programmers place the interface, in the form of a class definition, in a header file and place the implementation, in the form of code for the class methods, in a source code file.
C++ 程序员将接口 (类定义) 放在头文件中,并将实现 (类方法的代码) 放在源代码文件中。

In this context the keywords class and typename are not synonymous the way they were in template parameters; typename can’t be used here.
C++ 关键字 class 指出这些代码定义了一个类设计,在这里关键字 classtypename 不是同义词,不能使用 typename 代替 class (不同于在模板参数中)。Stock 是这个新类的类型名,该声明让我们能够声明 Stock 类型的变量称为对象或实例。

  • stock.h
#ifndef STOCK_H_
#define STOCK_H_#include <string>// class declaration
class Stock {
private:std::string company_;int shares_;double share_val_;double total_val_;void SetTot() { total_val_ = shares_ * share_val_; }
public:Stock();  // Default constructorStock(const std::string &company, const long num = 0, const double price = 0.0);~Stock();void Buy(const long num, const double price);void Sell(const long num, const double price);void Update(const double price);void Show()const;const Stock &TopVal(const Stock &stock) const;
}; // Note semicolon at the end#endif

1. Access Control (访问控制)

Also new are the keywords private and public. These labels describe access control for class members. Any program that uses an object of a particular class can access the public portions directly. A program can access the private members of an object only by using the public member functions (or via a friend function). For example, the only way to alter the shares_ member of the Stock class is to use one of the Stock member functions. Thus, the public member functions act as go-betweens between a program and an object’s private members; they provide the interface between object and program. This insulation of data from direct access by a program is called data hiding.
关键字 privatepublicprotected 描述了对类成员的访问控制。使用类对象的程序都可以直接访问公有部分,但只能通过公有成员函数 (或友元函数) 来访问对象的私有成员。例如,要修改 Stock 类的 shares_ 成员,只能通过 Stock 的成员函数。因此,公有成员函数是程序和对象的私有成员之间的桥梁,提供了对象和程序之间的接口。防止程序直接访问数据被称为数据隐藏。

insulation [ˌɪnsjʊˈleɪʃ(ə)n]:n. 绝缘,隔热,隔音,隔热材料

在这里插入图片描述

The Stock class.

A class design attempts to separate the public interface from the specifics of the implementation. The public interface represents the abstraction component of the design. Gathering the implementation details together and separating them from the abstraction is called encapsulation. Data hiding (putting data into the private section of a class) is an instance of encapsulation, and so is hiding functional details of an implementation in the private section, as the Stock class does with SetTot(). Another example of encapsulation is the usual practice of placing class function definitions in a separate file from the class declaration.
类设计尽可能将公有接口与实现细节分开。公有接口表示设计的抽象组件,将实现细节放在一起并将它们与抽象分开被称为封装。数据隐藏 (将数据放在类的私有部分中) 是一种封装,将实现的细节隐藏在私有部分中,就像 Stock 类对 SetTot() 所做的那样,也是一种封装。封装的另一个例子是将类函数定义和类声明放在不同的文件中。

OOP is a programming style that you can use to some degree with any language.
OOP 是一种编程风格,从某种程度说,它用于任何一种语言中。

Note that data hiding not only prevents you from accessing data directly, but it also absolves you (in the roll as a user of the class) from needing to know how the data is represented.
数据隐藏不仅可以防止直接访问数据,还让开发者 (类的用户) 无需了解数据是如何被表示的。

absolve [əbˈzɒlv]:v. 宣告 ... 无罪,判定 ... 无责,赦免 ... 的罪

2. Member Access Control (控制对成员的访问)

You can declare class members, whether they are data items or member functions, either in the public or the private section of a class. But because one of the main precepts of OOP is to hide the data, data items normally go into the private section. The member functions that constitute the class interface go into the public section; otherwise, you can’t call those functions from a program. As the Stock declaration shows, you can also put member functions in the private section. You can’t call such functions directly from a program, but the public methods can use them. Typically, you use private member functions to handle implementation details that don’t form part of the public interface.
无论类成员是数据成员还是成员函数,都可以在类的公有部分或私有部分中声明它。但由于隐藏数据是 OOP 主要的目标之一,因此数据项通常放在私有部分,组成类接口的成员函数放在公有部分;否则,就无法从程序中调用这些函数。正如 Stock 声明所表明的,也可以把成员函数放在私有部分中。不能直接从程序中调用这种函数,但公有方法却可以使用它们。通常,程序员使用私有成员函数来处理不属于公有接口的实现细节。

You don’t have to use the keyword private in class declarations because that is the default access control for class objects:

class World
{float mass_;  // private by defaultchar name_[20];  // private by default
public:void TellAll(void);...
};

However, this book explicitly uses the private label in order to emphasize the concept of data hiding.
然而,为强调数据隐藏的概念,本书显式地使用了 private

Class descriptions look much like structure declarations with the addition of member functions and the public and private visibility labels. In fact, C++ extends to structures the same features classes have. The only difference is that the default access type for a structure is public, whereas the default type for a class is private. C++ programmers commonly use classes to implement class descriptions while restricting structures to representing pure data objects (often called plain-old data structures, or POD structures).
类描述看上去很像是包含成员函数以及 publicprivate 可见性标签的结构声明。实际上,C++ 对 struct 进行了扩展,使之具有与 class 相同的特性。它们之间唯一的区别是,struct 的默认访问类型是 public,而 class 的默认访问类型为 privateC++ 程序员通常使用类来实现类描述,而把结构限制为只表示纯粹的数据对象,常被称为普通老式数据结构 (Plain Old Data,POD)。

2.2. Implementing Class Member Functions (实现类成员函数)

Member function definitions are much like regular function definitions. Each has a function header and a function body. Member function definitions can have return types and arguments. But they also have two special characteristics:

  • When you define a member function, you use the scope-resolution operator (::) to identify the class to which the function belongs.
    定义成员函数时,使用作用域解析运算符 (::) 来标识函数所属的类。
  • Class methods can access the private components of the class.
    类方法可以访问类的 private 组件。

The function header for a member function uses the scope-resolution operator (::) to indicate to which class the function belongs.
成员函数的函数头使用作用域运算符解析 (::) 来指出函数所属的类。

For example, the header for the Update() member function looks like this:

void Stock::Update(double price)

This notation means you are defining the Update() function that is a member of the Stock class. Not only does this identify Update() as a member function, it means you can use the same name for a member function for a different class.

For example, an Update() function for a Elephant class would have this function header:

void Elephant::Update()

Thus, the scope-resolution operator resolves the identity of the class to which a method definition applies. We say that the identifier Update() has class scope. Other member functions of the Stock class can, if necessary, use the Update() method without using the scope-resolution operator. That’s because they belong to the same class, making Update() in scope.
因此,作用域解析运算符确定了方法定义对应的类的身份。我们说,标识符 Update() 具有类作用域 (class scope)。Stock 类的其他成员函数不必使用作用域解析运算符就可以使用 Update() 方法,这是因为它们属于同一个类,因此 Update() 是可见的。

One way of looking at method names is that the complete name of a class method includes the class name. Stock::Update() is called the qualified name of the function. A simple Update(), on the other hand, is an abbreviation (the unqualified name) for the full name - one that can be used just in class scope.
类方法的完整名称中包括类名。Stock::Update() 是函数的限定名 (qualified name),而简单的 Update() 是全名的缩写 (非限定名,unqualified name) ,它只能在类作用域中使用。

The second special characteristic of methods is that a method can access the private members of a class.
方法可以访问类的私有成员。

If you try to use a nonmember function to access these data members, the compiler stops you cold in your tracks. (However, friend functions provide an exception.)
如果试图使用非成员函数访问这些数据成员,编译器禁止这样做 (友元函数例外)。

  • stock.cpp
#include <iostream>#include "stock.h"// Default constructor
Stock::Stock() {std::cout << "Stock::Stock()" << "\n";company_ = "default name";shares_ = 0;share_val_ = 0.0;total_val_ = 0.0;
}Stock::Stock(const std::string &company, const long num, const double price) {std::cout << "Stock::Stock(const std::string &company, const long num = 0, const double price = 0.0): " << company << "\n";company_ = company;if (num < 0) {std::cout << "Number of shares_ can't be negative; " << company_ << " shares_ set to 0.\n";shares_ = 0;}else {shares_ = num;}share_val_ = price;SetTot();
}// Destructor
Stock::~Stock() {std::cout << "Stock::~Stock(): " << company_ << "\n";
}void Stock::Buy(const long num, const double price) {if (num < 0) {std::cout << "Number of shares_ purchased can't be negative. " << "Transaction is aborted.\n";}else {shares_ += num;share_val_ = price;SetTot();}
}void Stock::Sell(const long num, const double price) {if (num < 0) {std::cout << "Number of shares_ sold can't be negative. " << "Transaction is aborted.\n";}else if (num > shares_) {std::cout << "You can't sell more than you have! " << "Transaction is aborted.\n";}else {shares_ -= num;share_val_ = price;SetTot();}
}void Stock::Update(const double price) {share_val_ = price;SetTot();
}void Stock::Show() const {// set format to #.###std::ios_base::fmtflags original = std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);std::streamsize precision = std::cout.precision(3);std::cout << "Company: " << company_ << "\n  Shares = " << shares_;std::cout << "  Share Price = $" << share_val_;// set format to #.##std::cout.precision(2);std::cout << "  Total Worth = $" << total_val_ << '\n';// restore original formatstd::cout.setf(original, std::ios_base::floatfield);std::cout.precision(precision);
}const Stock & Stock::TopVal(const Stock & stock) const {if (stock.total_val_ > total_val_) {return stock;  // argument object}else {return *this;  // invoking object}
}

1. Member Function Notes (成员函数说明)

Because this function is merely the means of implementing the code and not part of the public interface, the class makes SetTot() a private member function. (That is, SetTot() is a member function used by the person writing the class but not used by someone writing code that uses the class.)
由于 SetTot() 只是实现代码的一种方式,而不是公有接口的组成部分,因此这个类将其声明为私有成员函数 (即编写这个类的人可以使用它,但编写代码来使用这个类的人不能使用) 。

2. Inline Methods (内联方法)

Any function with a definition in the class declaration automatically becomes an inline function. Thus, Stock::SetTot() is an inline function. Class declarations often use inline functions for short member functions, and SetTot() qualifies on that account.
定义位于类声明中的函数都将自动成为内联函数,因此 Stock::SetTot() 是一个内联函数。类声明常将短小的成员函数作为内联函数,SetTot() 符合这样的要求。

You can, if you like, define a member function outside the class declaration and still make it inline. To do so, you just use the inline qualifier when you define the function in the class implementation section:
如果愿意,也可以在类声明之外定义成员函数,并使其成为内联函数。为此,只需在类实现部分中定义函数时使用 inline 限定符即可:

class Stock
{
private:...void SetTot(); // definition kept separate
public:...
};inline void Stock::SetTot() // use inline in definition
{total_val_ = shares_ * share_val_;
}

The special rules for inline functions require that they be defined in each file in which they are used. The easiest way to make sure that inline definitions are available to all files in a multifile program is to include the inline definition in the same header file in which the corresponding class is defined.
内联函数的特殊规则要求在每个使用它们的文件中都对其进行定义。确保内联定义对多文件程序中的所有文件都可用的、最简便的方法是:将内联定义放在定义类的头文件中 。

Incidentally, according to the rewrite rule, defining a method within a class declaration is equivalent to replacing the method definition with a prototype and then rewriting the definition as an inline function immediately after the class declaration. That is, the original inline definition of SetTot() is equivalent to the one just shown, with the definition following the class declaration.
根据改写规则 (rewrite rule),在类声明中定义方法等同于用原型替换方法定义,然后在类声明的后面将定义改写为内联函数。程序清单中 SetTot() 的内联定义与上述代码 (定义紧跟在类声明之后) 是等价的。

When you call a member function, it uses the data members of the particular object used to invoke the member function.
调用成员函数时,它将使用被用来调用它的对象的数据成员。

Each new object you create contains storage for its own internal variables, the class members. But all objects of the same class share the same set of class methods, with just one copy of each method.
所创建的每个新对象都有自己的存储空间,用于存储其内部变量和类成员;但同一个类的所有对象共享同一组类方法,即每种方法只有一个副本。

They just apply the code to different data. Calling a member function is what some OOP languages term sending a message. Thus, sending the same message to two different objects invokes the same method but applies it to two different objects
它们将执行同一个代码块,只是将这些代码用于不同的数据。在 OOP 中,调用成员函数被称为发送消息,因此将同样的消息发送给两个不同的对象将调用同一个方法,但该方法被用于两个不同的对象。

在这里插入图片描述

Objects, data, and member functions.

2.3. Using Classes (使用类)

The C++ goal is to make using classes as similar as possible to using the basic, built-in types, such as int and char. You can create a class object by declaring a class variable or using new to allocate an object of a class type.
C++ 的目标是使得使用类与使用基本的内置类型 (例如 intchar) 尽可能相同。要创建类对象,可以声明类变量,也可以使用 new 为类对象分配存储空间。

  • sample.cpp
#include <iostream>#include "stock.h"int main() {Stock yongqiang("strong", 20, 12.50);yongqiang.Show();yongqiang.Buy(15, 18.125);yongqiang.Show();yongqiang.Sell(400, 20.00);yongqiang.Show();yongqiang.Buy(300000, 40.125);yongqiang.Show();yongqiang.Sell(300000, 0.125);yongqiang.Show();return 0;
}

在这里插入图片描述

Stock::Stock(const std::string &company, const long num = 0, const double price = 0.0): strong
Company: strongShares = 20  Share Price = $12.500  Total Worth = $250.00
Company: strongShares = 35  Share Price = $18.125  Total Worth = $634.38
You can't sell more than you have! Transaction is aborted.
Company: strongShares = 35  Share Price = $18.125  Total Worth = $634.38
Company: strongShares = 300035  Share Price = $40.125  Total Worth = $12038904.38
Company: strongShares = 35  Share Price = $0.125  Total Worth = $4.38
Stock::~Stock(): strong
请按任意键继续. . .

1. The Client / Server Model

OOP programmers often discuss program design in terms of a client / server model. In this conceptualization, the client is a program that uses the class. The class declaration, including the class methods, constitute the server, which is a resource that is available to the programs that need it. The client uses the server through the publicly defined interface only. This means that the client’s only responsibility, and, by extension, the client’s programmer’s only responsibility, is to know that interface. The server’s responsibility, and, by extension, the server’s designer’s responsibility, is to

see that the server reliably and accurately performs according to that interface. Any changes the server designer makes to the class design should be to details of implementation, not to the interface. This allows programmers to improve the client and the server independently of each other, without changes in the server having unforeseen repercussions on the client’s behavior.
OOP 程序员常依照客户/服务器模型来讨论程序设计。在这个概念中,客户是使用类的程序。类声明 (包括类方法) 构成了服务器,它是程序可以使用的资源。客户只能通过以公有方式定义的接口使用服务器,这意味着客户 (客户程序员) 唯一的责任是了解该接口。服务器 (服务器设计人员) 的责任是确保服务器根据该接口可靠并准确地执行。服务器设计人员只能修改类设计的实现细节,而不能修改接口。这样程序员独立地对客户和服务器进行改进,对服务器的修改不会客户的行为造成意外的影响。

You can avoid e-notation by using the setf() method

std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);

This sets a flag in the std::cout object instructing cout to use fixed-point notation.
设置 std::cout 对象的一个标记,命令 std::cout 使用定点表示法。使用方法 std::cout.setf(),便可避免科学计数法

Similarly, the following statement causes std::cout to show three places to the right of the decimal when using fixed-point notation.
下面的语句设置 std::cout 在使用定点表示法时,显示 3 位小数

std::cout.precision(3);

The class declaration is modeled after a structure declaration and can include data members and function members. The declaration has a private section, and members declared in that section can be accessed only through the member functions. The declaration also has a public section, and members declared there can be accessed directly by a program using class objects.
类声明类似结构声明,可以包括数据成员和函数成员。声明私有部分,在其中声明的成员只能通过成员函数进行访问;声明公有部分,在其中声明的成员可被使用类对象的程序直接访问。通常,数据成员被放在私有部分中,成员函数被放在公有部分中。

Typically, data members go into the private section and member functions go into the public section, so a typical class declaration has this form:

class ClassName
{
private:data member declarations
public:member function prototypes
};

The contents of the public section constitute the abstract part of the design, the public interface. Encapsulating data in the private section protects the integrity of the data and is called data hiding.
公有部分的内容构成了设计的抽象部分 - 公有接口。将数据封装到私有部分中可以保护数据的完整性,这被称为数据隐藏。

You can use a complete function definition instead of a function prototype in the class declaration, but the usual practice, except with very brief functions, is to provide the function definitions separately. In that case, you need to use the scope-resolution operator to indicate to which class a member function belongs.
可以在类声明中提供完整的函数定义,而不是函数原型,但是通常的做法是单独提供函数定义 (除非函数很小)。在这种情况下,需要使用作用域解析运算符来指出成员函数属于哪个类。

For example, suppose the Giraffe class has a member function called Retort() that returns a pointer to a char. The function header would look like this:

char * Giraffe::Retort()

In other words, Retort() is not just a type char * function; it is a type char * function that belongs to the Giraffe class. The full, or qualified, name of the function is Giraffe::Retort().The name Retort(), on the other hand, is an abbreviation of the qualified name, and it can be used only in certain circumstances, such as in the code for the class methods.
Retort() 不仅是一个 char * 类型的函数,而是一个属于 Giraffe 类的 char * 函数。该函数的全名 (或限定名) 为 Giraffe::Retort()。而名称 Retort() 是限定名的缩写,只能在某些特定的环境中使用。

The name Retort() has class scope, so the scope-resolution operator is needed to qualify the name when it is used outside the class declaration and a class method.
名称 Retort() 的作用域为整个类,因此在类声明和类方法之外使用该名称时,需要使用作用域解析运算符进行限定。

要创建对象 (类的实例),只需将类名视为类型名即可:

Giraffe june;

This works because a class is a user-defined type. You invoke a class member function, or method, by using a class object. You do so by using the dot membership operator: std::cout << june.Retort();
这样做是可行的,因为类是用户定义的类型。类成员函数 (方法) 可通过类对象来调用。为此,需要使用成员运算符句点。

This invokes the Retort() member function, and whenever the code for that function refers to a particular data member, the function uses the value that member has in the june object.
这将调用 Retort() 成员函数,每当其中的代码引用某个数据成员时,该函数都将使用 june 对象中相应成员的值。

References

[1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/
[2] C++ Primer Plus, 6th Edition, https://www.informit.com/store/c-plus-plus-primer-plus-9780321776402

  • Procedural and Object-Oriented Programming
  • Abstraction and Classes

相关文章:

Objects and Classes (对象和类)

Objects and Classes [对象和类] 1. Procedural and Object-Oriented Programming (过程性编程和面向对象编程)2. Abstraction and Classes (抽象和类)2.1. Classes in C (C 中的类)2.2. Implementing Class Member Functions (实现类成员函数)2.3. Using Classes (使用类) Ref…...

从单点到全景:视频汇聚/安防监控EasyCVR全景视频监控技术的演进之路

在当今日新月异的科技浪潮中&#xff0c;安防监控领域的技术发展日新月异&#xff0c;全景摄像机便是这一领域的杰出代表。它以其独特的360度无死角监控能力&#xff0c;为各行各业提供了前所未有的安全保障&#xff0c;成为现代安防体系中的重要组成部分。 一、全景摄像机的技…...

Java学习 -Golang开发环境+目录结构+编译+部署

开发环境 环境变量设置 GOROOT 指定 golang sdk 的安装目录GOPATH golang 工作目录&#xff0c;项目的源码放在这个目录下PATH 将 GOROOT/bin 放在 Path 路径下&#xff0c;方便命令行能直接运行 golang的命令行工具项目目录结构 |--project // 位于G…...

Redis 典型应用——缓存(缓存预热,穿透,雪崩,击穿)

一、缓存 缓存是计算机中一个很经典的概念&#xff0c;核心思路是把一些常用的数据放到访问速度更快的地方&#xff0c;方便随时读取&#xff1b; 但对于计算机硬件来说&#xff0c;往往访问速度越快的设备&#xff0c;成本越高&#xff0c;存储空间越小&#xff0c;缓存是更…...

Sharding-JDBC分库分表的基本使用

前言 传统的小型应用通常一个项目一个数据库&#xff0c;单表的数据量在百万以内&#xff0c;对于数据库的操作不会成为系统性能的瓶颈。但是对于互联网应用&#xff0c;单表的数据量动辄上千万、上亿&#xff0c;此时通过数据库优化、索引优化等手段&#xff0c;对数据库操作…...

7月信用卡新规下:信用卡欠的钱不用还了?

说到信用卡&#xff0c;现在基本上人手一张&#xff0c;大家都有使用过。但你知道吗&#xff0c;使用信用卡不是这么简单容易的事&#xff0c;比如会对你的贷款有影响&#xff0c;透支不还逾期对生活的影响&#xff0c;信用卡新规对持卡人和银行那边的影响。 一、只要不逾期&am…...

坑——python的redis库的decode_responses设置

python的redis库查询返回的值默认是返回字节串&#xff0c;可以在redis.Redis()方法中通过设置decode_responses参数&#xff0c;让返回值直接是字符串&#xff1b; 查询返回字节串是因为Redis()方法中decode_responses默认值是False&#xff1a; 设置decode_responses为True就…...

从项目中学习Bus-Off的快慢恢复

0 前言 说到Bus-Off&#xff0c;大家应该都不陌生&#xff0c;使用VH6501干扰仪进行测试的文章在网上数不胜数&#xff0c;但是一般大家都是教怎么去干扰&#xff0c;但是说如何去看快慢恢复以及对快慢恢复做出解释比较少&#xff0c;因此本文以实践的视角来讲解Bus-Off的快慢恢…...

视频参考帧和重构帧复用

1、 视频编码中的参考帧和重构帧 从下图的编码框架可以看出&#xff0c;每编码一帧需要先使用当前帧CU(n)减去当前帧的参考帧CU&#xff08;n&#xff09;得到残差。同时&#xff0c;需要将当前帧的重构帧CU*&#xff08;n&#xff09;输出&#xff0c;然后再读取重构帧进行预测…...

js修改scss变量

style.scss $color : var(--color,#ccc); // 默认值 #ccc .color{background: $color; } 定义了一个scss变量&#xff08;$color&#xff09;&#xff0c;用普通的css变量&#xff08;--color&#xff09;给他赋值&#xff0c;这里需要一个默认值&#xff0c;此时css变量(--co…...

【中霖教育怎么样】报考注册会计师有年龄限制吗?

【中霖教育怎么样】报考注册会计师有年龄限制吗? 申请参加注册会计师考试有没有年龄约束? 对于注册会计师的考试&#xff0c;不存在具体的年龄上限。而且该考试的入学门栏相对低&#xff0c;主要对考生的年龄下限规定。 在专业阶段&#xff0c;注册会计师考试要求考生具备…...

PHP验证日本手机电话号码

首先&#xff0c;您需要了解手机号码的规格。 根据 &#xff0c;手机和PHS&#xff08;个人手持电话系统&#xff09;可以理解为以“070”、“080”和“090”开头的11位数字。 此外&#xff0c;以“050”开头的11位特定IP电话号码也将包含在该目标中。 关于以“060”开头的F…...

Qt 配置ASan

Qt 配置ASan 文章目录 Qt 配置ASan摘要关于ASan&#xff08;AddressSanitizer&#xff09;在Qt中配置 ASan1. 安装必要的工具2. 修改项目的 .pro 文件3. 重新构建项目4. 运行应用程序5. 分析错误报告示例注意事项 关键字&#xff1a; Qt、 ASan、 AddressSanitizer 、 GCC …...

MySQL常用操作命令大全

文章目录 一、连接与断开数据库1.1 连接数据库1.2 选择数据库1.3 断开数据库 二、数据库操作2.1 创建数据库2.2 查看数据库列表2.3 删除数据库 三、表操作3.1 创建表3.2 查看表结构3.3 修改表结构3.3.1 添加列3.3.2 删除列3.3.3 修改列数据类型 3.4 删除表 四、数据操作4.1 插入…...

有人物联的串口服务器USR-TCP232-410S基本测试通信和使用方案(485串口和232串口)

1.将 410S(USR-TCP232-410S&#xff0c;简称 410S 下同)的串口通过串口线(或USB 转串口线)与计算机相连接&#xff0c;通过网线将 410S 的网口 PC 的网口相连接&#xff0c;检测硬件连接无错误后&#xff0c;接入我们配送的电源适配器&#xff0c;给 410S 供电。观察指示灯状态…...

二维码登录的原理

二维码登录的原理: 二维码登录是一种基于移动设备和网络技术的便捷登录方式。其原理主要依赖于以下几个关键要素: 随机生成:服务器端随机生成一个具有唯一性和时效性的二维码。编码信息:这个二维码包含了特定的登录信息,例如用户标识、会话标识、时间戳等。扫描识别:用户…...

归并排序详解(递归与非递归)

归并排序是建立在归并操作上的一种有效算法。该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列有序&#xff0c;再使子序列间断有序。若将两个有序表合并成一个有序表&#xff0c;成为二路归并。 一…...

计算机系统基础(二)

1.数值数据的表示 为什么采用二进制&#xff1f; 二进制只有两种基本状态&#xff0c;两个物理器件就可以表示0和1二进制的编码、技术、运算规则都很简单0和1与逻辑命题的真假对应&#xff0c;方便通过逻辑门电路实现算术运算 数值数据表示的三要素 进位记数制&#xff08;十…...

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

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

leetcode-21-回溯-全排列及其去重

一、[46]全排列 给定一个 没有重复 数字的序列&#xff0c;返回其所有可能的全排列。 示例: 输入: [1,2,3]输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 其中&#xff0c;不需要使用startIndex used数组&#xff0c;其实就是记录此时path里都有哪些元素…...

如何根据两个关键字查询报错日志的位置

1、查找两个关键字&#xff08;无顺序要求&#xff09; 如果你不关心这两个关键字出现的顺序&#xff0c;你可以使用egrep&#xff08;等同于grep -E&#xff09;或grep的-E选项来启用扩展正则表达式&#xff0c;并使用管道&#xff08;|&#xff09;来组合两个搜索模式。 gr…...

短视频预算表:成都柏煜文化传媒有限公司

短视频预算表&#xff1a;精打细算&#xff0c;打造高质量视觉盛宴 在数字时代&#xff0c;短视频以其独特的魅力迅速占领了互联网内容的半壁江山&#xff0c;成为品牌宣传、文化传播乃至个人表达的重要载体。然而&#xff0c;每一个成功的短视频背后&#xff0c;都离不开一份…...

【Llama 2的使用方法】

Llama 2是Meta AI&#xff08;Facebook的母公司Meta的AI部门&#xff09;开发并开源的大型语言模型系列之一。Llama 2是在其前身Llama模型的基础上进行改进和扩展的&#xff0c;旨在提供更强大的自然语言处理能力和更广泛的应用场景。 以下是Llama 2的一些关键特性和更新点&am…...

mysql-sql-第十三周

学习目标&#xff1a; sql 学习内容&#xff1a; 37.查询各科成绩最高分、最低分和平均分&#xff1a; 以如下形式显示&#xff1a;课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率 及格为>60,中等为&#xff1a;70-80,优良为&#xff1a;80-90,优秀…...

【Android】ViewPage2嵌套Fragment+SeekBar横向滑动冲突

问题描述 ViewPage2嵌套FragmentSeekBar&#xff0c;拖动SeekBar的进度条时&#xff0c;触发ViewPage2的滑动。 解决方案&#xff1a; 方案一&#xff1a;通过事件总线ViewPage2的isUserInputEnabled属性 子Fragment&#xff1a; class SeekBarFragment : Fragment() {priv…...

【408考点之数据结构】图的遍历

图的遍历 图的遍历是指从图中的某个顶点出发&#xff0c;按照一定的规则访问图中所有顶点&#xff0c;并使每个顶点仅被访问一次。图的遍历包括两种主要方法&#xff1a;深度优先搜索&#xff08;DFS&#xff09;和广度优先搜索&#xff08;BFS&#xff09;。这两种遍历方法在…...

自动驾驶---Motion Planning之多段五次多项式

1 前言 在之前的博客系列文章中和读者朋友们聊过Apollo的 Motion Planning方案: 《自动驾驶---Motion Planning之LaneChange》 《自动驾驶---Motion Planning之Path Boundary》 《自动驾驶---Motion Planning之Speed Boundary》 《自动驾驶---Motion Planning之轨迹Path优化》…...

Linux基础IO操作详解

C文件IO相关接口 fopen函数 pathname: 要打开的文件名字符串mode: 访问文件的模式 模式描述含义“r”读文件不存在失败返回null“r”读写文件不存在打开失败返回null&#xff0c;文件存在则从头开始覆盖现有的数据&#xff08;不会清空数据&#xff09;“w”写文件不存在创建…...

轻松掌握:Hubstudio指纹浏览器如何接入IPXProxy代理IP

​代理IP对于保护个人和企业网络安全起到了至关重要的作用&#xff0c;然而在需要多个工作的时候&#xff0c;就需要搭配指纹浏览器来使用。其中Hubstudio指纹浏览器就可以模拟多个浏览器环境&#xff0c;然而有些用户不知道如何将Hubstudio和代理IP一起使用&#xff0c;下面以…...

React小记(五)_Hooks入门到进阶

React 16.8 版本 类组件 和 函数组件 两种组件共存&#xff0c;到目前 React 18 版本&#xff0c;官方已经不在推荐使用类组件&#xff0c;在函数组件中 hooks 是必不可少的&#xff0c;它允许我们函数组件像类组件一样可以使用组件的状态&#xff0c;并模拟组件的生命周期等一…...

使用工业自动化的功能块实现大语言模型应用

大语言模型无所不能&#xff1f; 以chatGPT为代表的大语言模型横空出世&#xff0c;在世界范围内掀起了一场AI革命。给人的感觉似乎大模型语言无所不能。它不仅能够生成文章&#xff0c;图片和视频&#xff0c;能够翻译文章&#xff0c;分析科学和医疗数据&#xff0c;甚至可以…...

PPT文件中,母版视图与修改权限的区别

在PPT&#xff08;PowerPoint&#xff09;制作过程中&#xff0c;母版视图和修改权限是两个重要的概念&#xff0c;它们各自在演示文稿的编辑、管理和分发中扮演着不同的角色。本文将从定义、功能、使用场景及区别等方面详细探讨PPT母版视图与修改权限的异同。 PPT母版视图 定…...

php简单的单例模式

本文由 ChatMoney团队出品 单例模式是一种常用的设计模式&#xff0c;它的核心思想是确保一个类只有一个实例&#xff0c;并提供一个全局访问点来获取这个实例。在 PHP 中实现单例模式通常有三种形式&#xff1a;饿汉式&#xff08;Eager&#xff09;、懒汉式&#xff08;Lazy&…...

【面试题】IPS(入侵防御系统)和IDS(入侵检测系统)的区别

IPS&#xff08;入侵防御系统&#xff09;和IDS&#xff08;入侵检测系统&#xff09;在网络安全领域扮演着不同的角色&#xff0c;它们之间的主要区别可以归纳如下&#xff1a; 功能差异&#xff1a; IPS&#xff1a;这是一种主动防护设备&#xff0c;不仅具备检测攻击的能力&…...

宠物博主亲测养宠好物安利,口碑好的狗毛空气净化器推荐

作为一名6年资深铲屎官&#xff0c;一到春季换季就开始各种疯狂打喷嚏、全身过敏红肿&#xff0c;这是因为宠物在换季的时候就疯狂掉毛&#xff0c;家里就想下雪一样&#xff0c;空气中都是宠物浮毛。而宠物毛上附带的细菌会跟随浮毛被人吸入人体&#xff0c;从而产生打喷嚏、过…...

常用工具类

计算当天开始时间和结束时间 DateTime date DateUtil.date(); String startDateStr DateUtil.formatDateTime(DateUtil.beginOfDay(date)); String endDateStr DateUtil.formatDateTime(DateUtil.beginOfDay(DateUtil.offsetDay(date,1))); params.put("startDate&quo…...

【数据库原理】总结(期末版)

题型关系范式题[数据库原理]关系范式总结&#xff08;自用&#xff09;-CSDN博客事务分析题[数据库原理]事务-CSDN博客Sql题 MySQL:MySQL基本语法 Oracle:Oracle基本语法 ​​​​​​ 关系代数[数据库原理]关系代数-CSDN博客 sql里面主要是考增删改查授权撤销权限等内容&#…...

【算能全国产AI盒子】基于BM1688CV186AH+FPGA智能物联工作站,支持差异化泛AI视觉产品定制

在数据呈现指数级增长的今天&#xff0c;越来越多的领域和细分场景对实时、高效的数据处理和分析的需求日益增长&#xff0c;对智能算力的需求也不断增强。为应对新的市场趋势&#xff0c;凭借自身的硬件研发优势&#xff0c;携手算能相继推出了基于BM1684的边缘计算盒子&#…...

材质相关内容整理 -ThreeJs

在Three.js中&#xff0c;材质是用来定义3D对象外观的关键部分。Three.js支持多种材质文件和类型&#xff0c;每种材质都有其特定的用途和优势。下面简单整理了一下目前Three.js支持的材质文件和类型。 一、Three.js支持的材质文件类型 JPEG (.jpg) 和 PNG (.png) 用途&#x…...

ES 嵌套查询

背景 一个配方由多种原材料组成&#xff0c;需求是根据各种原材料的用量搜索出对应的配方 配方实体类 class Formula {private long id;private String name;private List<Material> materials;}class Material {JsonProperty("material_id")private long m…...

《等保测评实战指南:从评估到加固的全程解析》

在当今数字化时代&#xff0c;信息安全已成为企业生存与发展的基石。随着网络攻击手段的不断演变和复杂度的提升&#xff0c;信息系统等级保护&#xff08;简称“等保”&#xff09;作为国家信息安全保障体系的重要组成部分&#xff0c;其重要性日益凸显。《等保测评实战指南&a…...

【24考研·交通】我的考研经历

文章目录 一、考前准备二、政治备考三、英语一备考四、数学一备考五、运筹学备考六、复试/调剂七、结语 距离24考研上考场过去快半年了&#xff0c;距离我拟录取也两个月多了&#xff0c;现在回想起来&#xff0c;最大的感受是&#xff1a;好像做了一场大梦。 其实这篇文章在考…...

ERP系统中有哪些模块?有哪些具体实现方案呢?

对于许多初次接触ERP系统的企业来说&#xff0c;可能会对系统中包含的模块和功能感到困惑。本文将详细介绍ERP系统中的主要模块&#xff0c;需要明确的是&#xff0c;ERP系统是一个庞大的系统&#xff0c;包含了多个模块&#xff0c;每个模块都有其独特的功能和作用。这些模块涵…...

扩散模型在机器学习中的应用及原理

扩散模型在机器学习中的应用及原理 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 什么是扩散模型&#xff1f; 在机器学习中&#xff0c;扩散模型&#xff…...

fastapi自定义中间件

fastapi自定义中间件 1、自定义中间件类 from fastapi import Request from starlette.middleware.base import BaseHTTPMiddlewareclass MyMiddleware(BaseHTTPMiddleware):def __init__(self, app,*args, **kwargs):super().__init__(app,*args, **kwargs)async def dispat…...

基于 MCU 的开发,能不能对代码进行单元测试?

在基于微控制器&#xff08;MCU&#xff09;的开发中&#xff0c;确实可以对代码进行单元测试&#xff0c;并且随着嵌入式软件开发实践的发展&#xff0c;越来越多的团队开始重视并实施单元测试和自动化测试。 单元测试是一种软件测试方法&#xff0c;用于验证程序模块&#xf…...

基于OpenCV与Keras的停车场车位自动识别系统

本项目旨在利用计算机视觉技术和深度学习算法&#xff0c;实现对停车场车位状态的实时自动识别。通过摄像头监控停车场内部&#xff0c;系统能够高效准确地辨认车位是否被占用&#xff0c;为车主提供实时的空闲车位信息&#xff0c;同时为停车场管理者提供智能化的车位管理工具…...

YOLOv10改进教程|C2f-CIB加入注意力机制

一、 导读 论文链接&#xff1a;https://arxiv.org/abs/2311.11587 代码链接&#xff1a;GitHub - CV-ZhangXin/AKConv YOLOv10训练、验证及推理教程 二、 C2f-CIB加入注意力机制 2.1 复制代码 打开ultralytics->nn->modules->block.py文件&#xff0c;复制SE注意力机…...

算法训练营day06 哈希表(统计数,去重,降低时间复杂度)

&#x1f4a1; 解题思路 &#x1f4dd; 确定输入与输出&#x1f50d; 分析复杂度&#x1f528; 复杂题目拆分 &#xff1a;严谨且完整 地拆分为更小的子问题&#xff08;哈希表的使用场景&#xff09;–&#xff08;多总结&#xff09;&#x1f4ad; 选择处理逻辑&#xff1a;…...

影帝郭晋安关联保健品企业,草姬集团无研发费用销售成本不低

《港湾商业观察》黄懿 5月30日&#xff0c;草姬集团控股有限公司&#xff08;下称“草姬集团”&#xff09;递表港交所主板&#xff0c;农银国际为其独家保荐人。 草姬集团成立于1999年&#xff0c;是中国香港多元化保健品、美容与护肤品供应商&#xff0c;由TVB港星郭晋安及…...

计算机网络笔记分享(第五章 运输层)

文章目录 五、运输层5.1 运输层协议概述5.2 UDP 用户数据报协议5.3 TCP 传输控制协议概述5.4 可靠传输的工作原理5.5 TCP报文段的首部格式5.6 TCP可靠传输的实现&#xff08;重点&#xff09;以字节为单位的滑动窗口超时重传时间的选择选择确认SACK 5.7 TCP的流量控制5.8 TCP的…...

Apache Seata透过源码解决SeataAT模式整合Mybatis-Plus失去MP特性的问题

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Apache Seata透过源码解决SeataAT模式整合Mybatis-Plus失去MP特性的问题 透过源码解决SeataAT…...

Java事务(Transaction)

Java事务&#xff08;Transaction&#xff09;是数据库管理系统执行过程中的一个逻辑单位&#xff0c;由一个有限的数据库操作序列组成&#xff0c;这些操作要么全部执行&#xff0c;要么全部不执行&#xff0c;是一个不可分割的工作单位。事务的引入主要是为了解决并发操作数据…...

【手机取证】如何使用360加固助手给apk加固

文章关键词&#xff1a;手机取证、电子数据取证、数据恢复 一、前言 APP加固是对APP代码逻辑的一种保护。原理是将应用文件进行某种形式的转换&#xff0c;包括不限于隐藏&#xff0c;混淆&#xff0c;加密等操作&#xff0c;进一步保护软件的利益不受损坏&#xff0c;下面给…...

如何使用Xcode查看iOS APP客户端日志

在测试iOS app过程中&#xff0c;能够有效查看和分析客户端日志是至关重要的。不论是定位crash还是解决复杂的逻辑错误&#xff0c;日志都扮演了不可或缺的角色。Apple的Xcode提供了一个强大的工具集&#xff0c;帮助测试同学有效地进行日志查看和分析。本文将逐步指导如何使用…...

tongweb 部署软航流版签一体化应用示例 提示跨域错误CORS ERROR

目录 问题现象与描述 解决办法 原理解析 什么是CORS 浏览器跨域请求限制 跨域问题解决方法 跨域请求流程 浏览器请求分类解析 http请求方法简介 问题现象与描述 重庆软航科技有限公司提供了一套针对针对word、excel等流式文件转换成PDF版式文件并进行版式文件在线签章…...

必胜客之后,DQ冰淇淋也跨界卖汉堡了

汉堡界又迎来一重磅新玩家。近日,DQ冰淇淋在其官方微博、小红书等社交媒体上发文称,DQ汉堡全国首店将于7月10日登陆上海。新玩家入局同时,哈比特汉堡、摩斯汉堡等一批“老玩家”却遗憾陆续退出中国市场。汉堡界,似乎从来不缺新故事。01.冰淇淋“专家”卖汉堡29元起卖,不“…...

NBA总决赛揭幕体育博彩业寄望篮球盛宴提振业绩

智通财经APP获悉,随着周四晚上NBA总决赛的揭幕,波士顿凯尔特人队正准备迎战达拉斯小牛队,争夺篮球界的最高荣誉。这场七场四胜制的较量不仅在球场上备受瞩目,更在体育博彩界引发了热潮。BetMGM的首席营收官马特普雷沃斯特表示:“NBA总决赛是年度体育赛事的重头戏,它吸引了…...

五菱高管发文“明年更卷”,消费者:车市越卷,我越幸福

日前,上汽通用五菱品牌事业部副总经理周钘在社交平台上发文称,“2024年初至今,宝骏停掉了所有的市场费用。企业认为如果产品、市场、渠道三者节奏都不对则是‘白费’”,“虽然今年行业确实卷,明年会更卷,但我们所有准备”。周钘从车企的角度,说出了车市竞争的残酷。不仅…...

salesforce 公式字段 判断一个字段是否在某个多选列表中

在 Salesforce 中&#xff0c;你可以使用公式字段来判断一个字段的值是否在一个多选列表中。这通常涉及使用包含特定值的函数和一些字符串操作。以下是一个常见的方法&#xff1a; 假设你有一个多选列表字段 Multi_Select_Field__c&#xff0c;你想检查这个字段是否包含某个值…...

【openlayers系统学习】1.6下载要素,将要素数据序列化为 GeoJSON并下载

六、下载要素 下载要素 上传数据并编辑后&#xff0c;我们想让用户下载结果。为此&#xff0c;我们将要素数据序列化为 GeoJSON&#xff0c;并创建一个带有 download​ 属性的 <a>​ 元素&#xff0c;该属性会触发浏览器的文件保存对话框。同时&#xff0c;我们将在地图…...

学习前端滚动容器

学习前端滚动容器 一、前言1、创建基本的滚动容器组件2、解析代码 二、示例应用1、使用滚动容器组件2、创建滚动容器组件结语 一、前言 滚动容器是指在页面布局中可以垂直或水平滚动其内容的区域。这种技术通常用于处理内容过长而导致溢出的情况&#xff0c;例如长表单、大段文…...