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

c++类全面讲解

文章目录

  • 前言
  • 类的基本概念
    • 基本结构
    • 类与结构体的区别
    • 示例代码
  • 类的属性和方法
    • 属性(成员变量)
    • 方法(成员函数)
    • 访问修饰符
    • 示例代码
  • 类的构造函数和析构函数
    • 构造函数
    • 析构函数
    • 示例代码
  • 类的构造函数重载
    • 重载构造函数
    • 示例代码
  • 类中的拷贝构造函数和赋值运算符
    • 拷贝构造函数
    • 赋值运算符
    • 示例代码
  • 类中的静态成员
      • 静态成员变量
      • 静态成员函数
      • 示例代码
  • 类中的继承
    • 继承的类型
    • 示例代码公有继承
    • 示例代码:私有继承
    • 示例代码:保护继承
  • 多态
    • 多态的类型
    • 虚函数和动态多态
      • 示例代码
  • 友元函数和友元类
    • 友元函数
    • 友元类
    • 示例代码
  • 运算符重载
    • 运算符重载的基本概念
    • 示例代码
  • 模板类
    • 模板类的基本概念
    • 示例代码
  • 高级特性
    • 虚继承
    • 多重继承
    • 抽象类
    • 接口
    • 虚继承示例代码
    • 多重继承
    • 示例代码:多重继承
    • 抽象类
    • 示例代码:抽象类
    • 接口
    • 示例代码:接口
  • 总结
    • 万字长文,朋友们点赞、关注啊!!!


前言

这次主要讲类的基础、构造函数与析构函数的使用,以及继承和多态。


类的基本概念

在C++中,类是一种用于创建对象的数据结构,它封装了数据(属性)和操作这些数据的方法(函数)。类定义了对象的特性和行为。

基本结构

一个类通常包括以下部分:

  • 数据成员:代表对象的属性。
  • 成员函数:定义对象可以执行的操作。
  • 访问修饰符:如 publicprivateprotected,用于控制成员的访问权限。

类与结构体的区别

  • 在C++中,类和结构体非常相似,但一个主要区别是默认的访问权限。在类中,默认的成员访问权限是私有(private),而在结构体中,默认是公有(public)。

示例代码

下面是一个简单的类定义和使用的例子:

#include <iostream>
#include <string>// 定义一个类
class Person {
public:     // 公有访问修饰符// 构造函数Person(std::string name, int age) : name(name), age(age) {}// 成员函数void introduce() {std::cout << "Name: " << name << ", Age: " << age << std::endl;}private:    // 私有访问修饰符// 数据成员std::string name;int age;
};int main() {// 创建Person类的对象Person person("Alice", 30);// 调用成员函数person.introduce();return 0;
}

在这个例子中:

  • Person 类有两个私有数据成员:nameage
  • 类有一个公共构造函数,它接受 nameage 参数来初始化对象。
  • introduce 是一个公共成员函数,用于打印对象的信息。
  • main 函数中,我们创建了一个 Person 对象并调用了它的 introduce 方法。

当然,让我们详细探讨C++中类的属性和方法,同时提供一个完整的代码示例。

类的属性和方法

属性(成员变量)

  • 属性是类中定义的变量,它们代表对象的状态或特性。在类中声明属性,可以使得每个对象都有自己的一套属性。

方法(成员函数)

  • 方法是类中定义的函数,它们用于执行操作,可以访问和修改对象的属性。方法提供了与对象交互的接口。

访问修饰符

  • 访问修饰符决定了类成员的访问级别。最常用的有三种:
    • public:可以被任何外部代码访问。
    • private:只能被类的其他成员(方法或友元)访问。
    • protected:只能被类本身、派生类及友元访问。

示例代码

下面是一个类的属性和方法的简单示例:

#include <iostream>
#include <string>class Car {
public:// 构造函数Car(std::string model, int year) : model(model), year(year) {}// 公共方法void displayInfo() {std::cout << "Car Model: " << model << ", Year: " << year << std::endl;}// 设置年份void setYear(int newYear) {year = newYear;}// 获取年份int getYear() {return year;}private:// 私有属性std::string model;int year;
};int main() {// 创建Car类的对象Car myCar("Toyota", 2020);// 调用公共方法myCar.displayInfo();// 更新年份myCar.setYear(2022);// 再次显示信息myCar.displayInfo();return 0;
}

在这个例子中:

  • Car 类有两个私有属性:modelyear
  • 公共方法 displayInfo 用于打印汽车信息。
  • 另外两个公共方法 setYeargetYear 分别用于设置和获取年份。
  • main 函数中,我们创建了一个 Car 对象,展示了如何使用这些方法来操作对象的状态。

类的构造函数和析构函数

构造函数

  • 构造函数在创建类的对象时自动调用。
  • 它的主要作用是初始化对象的属性。
  • 构造函数的名称与类名相同,并且没有返回类型。
  • 可以有参数,也可以没有(默认构造函数)。
  • 可以进行重载,即一个类可以有多个构造函数,只要它们的参数列表不同。

析构函数

  • 析构函数在对象销毁时自动调用。
  • 它的主要作用是进行清理工作,如释放资源、关闭文件等。
  • 析构函数的名称是类名前加上波浪符号(~),没有返回类型,也不接受参数。
  • 每个类只能有一个析构函数。

示例代码

下面是一个包含构造函数和析构函数的C++类示例:

#include <iostream>
#include <string>class Book {
public:// 构造函数Book(std::string title, std::string author) : title(title), author(author) {std::cout << "Book '" << title << "' by " << author << " created." << std::endl;}// 析构函数~Book() {std::cout << "Book '" << title << "' by " << author << " destroyed." << std::endl;}// 显示书籍信息的方法void displayInfo() {std::cout << "Title: " << title << ", Author: " << author << std::endl;}private:std::string title;std::string author;
};int main() {// 创建Book对象Book myBook("1984", "George Orwell");// 使用对象的方法myBook.displayInfo();// 对象myBook在这里会被自动销毁,调用析构函数return 0;
}

在这个例子中:

  • Book 类有两个私有属性:titleauthor
  • 它有一个构造函数,用于初始化这些属性,并打印一条创建消息。
  • 还有一个析构函数,当对象被销毁时,它会打印一条销毁消息。
  • main 函数中创建了一个 Book 对象,然后调用了它的 displayInfo 方法。程序结束时,myBook 对象的析构函数会被自动调用。

构造函数和析构函数使得对象的初始化和销毁自动执行,有助于管理资源和避免内存泄漏。

类的构造函数重载

在C++中,可以为一个类定义多个构造函数,只要它们的参数列表不同。这就是所谓的构造函数重载。重载构造函数允许以不同的方式初始化同一个类的对象。

重载构造函数

  • 目的:提供不同的方式来初始化对象。
  • 方法:在同一个类中定义多个构造函数,每个构造函数的参数类型、个数或顺序至少有一个不同。
  • 使用场景:需要根据不同的数据或条件创建对象时非常有用。

示例代码

下面的例子演示了如何在C++中重载构造函数:

#include <iostream>
#include <string>class Rectangle {
public:// 构造函数1:接受两个参数Rectangle(int w, int h) : width(w), height(h) {std::cout << "Rectangle created with width " << width << " and height " << height << std::endl;}// 构造函数2:接受一个参数explicit Rectangle(int size) : width(size), height(size) {std::cout << "Square created with size " << size << std::endl;}// 方法:计算面积int getArea() const {return width * height;}private:int width, height;
};int main() {// 使用第一个构造函数Rectangle rect1(10, 20);// 使用第二个构造函数Rectangle rect2(10);std::cout << "Area of rect1: " << rect1.getArea() << std::endl;std::cout << "Area of rect2: " << rect2.getArea() << std::endl;return 0;
}

在这个例子中:

  • Rectangle 类有两个构造函数。第一个接受两个参数(宽和高),第二个仅接受一个参数(正方形的边长)。
  • 两个构造函数具有不同的参数列表,因此它们被重载了。
  • main 函数中,我们分别使用两种不同的构造函数创建了两个 Rectangle 对象。

通过重载构造函数,Rectangle 类可以灵活地根据提供的参数来初始化对象,使得对象的创建更加灵活。

类中的拷贝构造函数和赋值运算符

拷贝构造函数

  • 拷贝构造函数在创建类的一个新对象时使用另一个对象的内容进行初始化时调用。
  • 它通常有一个参数,即对同类型对象的引用。
  • 如果没有自定义拷贝构造函数,编译器会提供一个默认的拷贝构造函数,进行逐成员的拷贝。

赋值运算符

  • 赋值运算符用于将一个对象的内容复制到另一个已经存在的对象中。
  • 与拷贝构造函数不同,赋值运算符在对象已经初始化后使用。
  • 如果不自定义赋值运算符,编译器将提供一个默认的,进行逐成员的赋值。

示例代码

下面是一个展示拷贝构造函数和赋值运算符使用的示例:

#include <iostream>
#include <string>class Person {
public:// 构造函数Person(std::string name) : name(name) {}// 拷贝构造函数Person(const Person& other) : name(other.name) {std::cout << "Copied Person: " << name << std::endl;}// 赋值运算符Person& operator=(const Person& other) {if (this != &other) { // 防止自赋值name = other.name;}return *this;}// 显示姓名void printName() {std::cout << "Person's name is: " << name << std::endl;}private:std::string name;
};int main() {Person person1("Alice");Person person2 = person1; // 调用拷贝构造函数Person person3("Bob");person3 = person1; // 调用赋值运算符person1.printName();person2.printName();person3.printName();return 0;
}

在这个示例中:

  • Person 类包含一个构造函数、一个拷贝构造函数和一个赋值运算符。
  • 当我们用 person1 初始化 person2 时,调用了拷贝构造函数。
  • 当我们将 person1 赋值给 person3 时,调用了赋值运算符。

拷贝构造函数和赋值运算符对于管理资源(如动态分配的内存)非常重要,可以防止诸如浅拷贝和资源泄漏等问题。在设计类时,根据需要合理地实现这两个函数是非常重要的。

类中的静态成员

静态成员可以是变量或函数,它们属于类本身,而不是类的任何特定对象。这意味着静态成员由类的所有对象共享。

静态成员变量

  • 静态成员变量是类的所有对象共享的变量。它们不属于任何单个对象。
  • 静态变量在程序的生命周期内只被初始化一次,并且在类的所有对象之间共享。
  • 它们通常用于存储类级别的信息,比如对象计数。

静态成员函数

  • 静态成员函数可以在不创建类的对象的情况下调用。
  • 它们只能访问静态成员变量和其他静态成员函数。
  • 通常用于执行不依赖于对象状态的操作。

示例代码

以下是一个包含静态成员的C++类的示例:

#include <iostream>class MyClass {
public:// 构造函数MyClass() {// 每创建一个对象,计数器增加objectCount++;}// 静态成员函数static int getObjectCount() {return objectCount;}private:// 静态成员变量static int objectCount;
};// 初始化静态成员变量
int MyClass::objectCount = 0;int main() {MyClass obj1;MyClass obj2;MyClass obj3;// 直接通过类名调用静态成员函数std::cout << "Total objects: " << MyClass::getObjectCount() << std::endl;return 0;
}

在这个例子中:

  • MyClass 类有一个静态成员变量 objectCount,用于跟踪创建的对象数量。
  • 类中有一个静态成员函数 getObjectCount,它返回 objectCount 的值。
  • main 函数中,我们创建了三个 MyClass 的对象,并通过类名直接调用 getObjectCount 来显示创建的对象总数。

类中的继承

继承是面向对象编程的一个基本概念,它允许基于一个类(基类)创建一个新的类(派生类)。这种机制提供了代码重用和层次化分类的能力。

继承的类型

  • 公有继承(public inheritance):基类的公有成员和保护成员在派生类中保持其原有的访问级别。
  • 保护继承(protected inheritance):基类的公有成员和保护成员在派生类中变成保护成员。
  • 私有继承(private inheritance):基类的公有成员和保护成员在派生类中变成私有成员。

示例代码公有继承

#include <iostream>
#include <string>// 基类
class Animal {
public:Animal(std::string name) : name(name) {}void eat() {std::cout << name << " is eating." << std::endl;}protected:std::string name;
};// 派生类
class Dog : public Animal {
public:Dog(std::string name) : Animal(name) {}void bark() {std::cout << name << " is barking." << std::endl;}
};int main() {Dog myDog("Buddy");myDog.eat();  // 调用基类方法myDog.bark(); // 调用派生类方法return 0;
}

在这个例子中:

  • Animal 是一个基类,具有一个公有方法 eat 和一个受保护的成员变量 name
  • Dog 是从 Animal 公有继承而来的派生类。它继承了 Animal 的特性,并添加了自己的方法 bark
  • main 函数中,我们创建了一个 Dog 对象,可以调用从基类继承的 eat 方法以及派生类的 bark 方法。

当然,我可以提供私有继承和保护继承的示例,以进一步阐释这些继承类型在C++中的应用。

示例代码:私有继承

#include <iostream>
#include <string>// 基类
class Vehicle {
public:Vehicle(std::string type) : type(type) {}protected:std::string type;
};// 派生类 - 私有继承
class Car : private Vehicle {
public:Car(std::string type) : Vehicle(type) {}void showType() {std::cout << "Car type: " << type << std::endl; // 可以访问基类的保护成员}
};int main() {Car myCar("SUV");myCar.showType(); // 正确// 下面的代码将会产生编译错误,因为type在Car中是私有的// std::cout << myCar.type << std::endl;return 0;
}

示例代码:保护继承

#include <iostream>
#include <string>// 基类
class Device {
public:Device(std::string name) : name(name) {}protected:std::string name;
};// 派生类 - 保护继承
class Printer : protected Device {
public:Printer(std::string name) : Device(name) {}void printName() {std::cout << "Printer name: " << name << std::endl; // 可以访问基类的保护成员}
};int main() {Printer myPrinter("HP LaserJet");myPrinter.printName(); // 正确// 下面的代码将会产生编译错误,因为name在Printer中是保护的// std::cout << myPrinter.name << std::endl;return 0;
}

多态

多态是面向对象编程的一个核心概念,允许对象以不同的方式响应相同的消息(或方法调用)。在C++中,多态主要通过虚函数(virtual functions)实现。

多态的类型

  • 编译时多态:也称为静态多态,主要通过函数重载和运算符重载实现。
  • 运行时多态:也称为动态多态,主要通过虚函数和函数覆盖(override)实现。

虚函数和动态多态

  • 虚函数允许派生类重写(override)基类中的函数。
  • 使用虚函数时,类的行为将根据对象的实际类型,而非其声明类型来确定。
  • 动态多态只能通过指针或引用来实现。

示例代码

以下是一个展示C++中使用虚函数实现多态的示例:

#include <iostream>// 基类
class Shape {
public:// 虚函数virtual void draw() const {std::cout << "Drawing a shape." << std::endl;}// 虚析构函数virtual ~Shape() {}
};// 派生类1
class Circle : public Shape {
public:void draw() const override { // 重写虚函数std::cout << "Drawing a circle." << std::endl;}
};// 派生类2
class Rectangle : public Shape {
public:void draw() const override { // 重写虚函数std::cout << "Drawing a rectangle." << std::endl;}
};void drawShape(const Shape& shape) {shape.draw(); // 动态绑定
}int main() {Circle circle;Rectangle rectangle;drawShape(circle);    // 输出: Drawing a circle.drawShape(rectangle); // 输出: Drawing a rectangle.return 0;
}

在这个示例中:

  • Shape 是一个基类,具有一个虚函数 draw 和一个虚析构函数。
  • CircleRectangle 是从 Shape 派生的类,它们重写了 draw 方法。
  • drawShape 函数接受一个 Shape 类型的引用,并调用 draw 方法。由于 draw 是虚函数,实际调用的是对象的动态类型对应的方法,这就是多态的体现。

友元函数和友元类

友元在C++中是一种特殊的机制,允许特定的函数或类访问另一个类的私有(private)和保护(protected)成员。

友元函数

  • 友元函数不是类的成员,但它可以访问类的所有私有和保护成员。
  • 友元函数通过在类内部使用 friend 关键字声明。
  • 友元函数常用于操作两个类的私有数据,例如,重载某些运算符时。

友元类

  • 友元类的所有成员函数都可以访问另一个类的私有和保护成员。
  • 通过将一个类声明为另一个类的友元,可以提高类间的耦合性。
  • 友元关系不是相互的。如果类A是类B的友元,这并不意味着类B是类A的友元。

示例代码

以下是展示友元函数和友元类的示例:

#include <iostream>// 前向声明
class Box;class Contents {
public:explicit Contents(int value) : value(value) {}// 友元函数声明friend void showContents(const Box& b);private:int value;
};class Box {
public:explicit Box(int secret) : secret(secret) {}// 友元类声明friend class SecretInspector;private:int secret;Contents contents{123}; // 假设内容是私有的
};// 友元类
class SecretInspector {
public:void inspect(const Box& b) {std::cout << "Box secret: " << b.secret << std::endl;}
};// 友元函数实现
void showContents(const Box& b) {std::cout << "Box contents: " << b.contents.value << std::endl;
}int main() {Box myBox(42);SecretInspector inspector;inspector.inspect(myBox); // 访问Box的私有数据showContents(myBox); // 访问Box中Contents的私有数据return 0;
}

在这个示例中:

  • Box 类有一个私有成员 secret 和一个私有嵌套对象 contents
  • SecretInspector 类被声明为 Box 的友元类,因此它可以访问 Box 的所有私有成员。
  • showContents 函数被声明为 Box 的友元函数,因此它可以访问 Box 中的 contents 的私有成员。

运算符重载

运算符重载是一种形式的多态,允许你定义或改变运算符(如 +, -, *, / 等)在自定义类型(如类或结构体)上的行为。

运算符重载的基本概念

  • 目的:使自定义类型的对象可以使用标准运算符进行操作。
  • 方法:通过在类内定义一个特殊的成员函数或友元函数来实现。这个函数使用 operator 关键字后跟要重载的运算符符号。
  • 限制:不能创建新的运算符,只能重载已有的运算符。某些运算符(如 ::, .*, .?:)不能被重载。

示例代码

下面是一个如何重载加法运算符的示例:

#include <iostream>class Coordinate {
public:Coordinate(int x, int y) : x(x), y(y) {}// 运算符 '+' 重载Coordinate operator+(const Coordinate& other) const {return Coordinate(x + other.x, y + other.y);}// 输出坐标的友元函数friend std::ostream& operator<<(std::ostream& os, const Coordinate& coord);private:int x, y;
};// 输出运算符 '<<' 的重载
std::ostream& operator<<(std::ostream& os, const Coordinate& coord) {os << "(" << coord.x << ", " << coord.y << ")";return os;
}int main() {Coordinate point1(1, 2);Coordinate point2(3, 4);Coordinate sum = point1 + point2;std::cout << "Sum of coordinates: " << sum << std::endl;return 0;
}

在这个示例中:

  • Coordinate 类重载了加法运算符(+),使其能够用于两个坐标对象的加法。
  • 重载运算符+返回一个新的 Coordinate 对象,其 xy 值是两个操作数对象的 xy 值之和。
  • 同时,为了能够方便地打印坐标,重载了输出运算符(<<)。

模板类

模板类是一种强大的C++特性,允许编写与数据类型无关的通用代码。

模板类的基本概念

  • 目的:实现代码的泛型编程,即相同的代码可以用于不同的数据类型。
  • 方法:使用关键字 template 定义模板,后面跟一个或多个模板参数。
  • 使用场景:当你需要类似的行为对多种数据类型执行时,比如容器类(如 vectormap 等)。

示例代码

以下是一个定义和使用模板类的示例:

#include <iostream>// 模板类定义
template<typename T>
class Box {
public:Box(T content) : content(content) {}T getContent() {return content;}private:T content;
};int main() {// 使用模板类创建整数盒子Box<int> intBox(123);// 使用模板类创建字符串盒子Box<std::string> stringBox("Hello World");std::cout << "Integer Box contains: " << intBox.getContent() << std::endl;std::cout << "String Box contains: " << stringBox.getContent() << std::endl;return 0;
}

在这个示例中:

  • Box 类是一个模板类,它有一个模板参数 T。这个 T 可以在创建 Box 对象时被替换为任何类型。
  • 类中的 content 成员变量和 getContent 方法都使用了模板参数 T
  • main 函数中,我们创建了两个 Box 对象:一个用于整数 (int),另一个用于字符串 (std::string)。

高级特性

虚继承

  • 用途:解决多重继承中的菱形继承问题(即两个派生类继承自同一个基类,再被另一个类同时继承时的冗余和歧义问题)。
  • 实现:通过 virtual 关键字在继承时使用。

多重继承

  • 用途:允许一个类同时从多个基类继承。
  • 注意事项:需要小心处理由多个基类引入的复杂性,如成员冲突和菱形继承问题。

抽象类

  • 用途:作为基类,定义一个接口,但不完全实现所有功能,留给派生类去实现。
  • 特点:包含至少一个纯虚函数(用 = 0 表示)。

接口

  • 概念:在C++中通常通过完全抽象的类实现(即所有成员函数都是纯虚函数)。
  • 用途:定义一个类必须遵循的方法,但不提供任何实现。

虚继承示例代码

#include <iostream>class Base {
public:virtual void print() {std::cout << "Base" << std::endl;}
};// 虚继承
class Derived1 : virtual public Base {
public:void print() override {std::cout << "Derived1" << std::endl;}
};class Derived2 : virtual public Base {
public:void print() override {std::cout << "Derived2" << std::endl;}
};class Final : public Derived1, public Derived2 {
public:// 调用最近的覆盖void print() override {Derived2::print();}
};int main() {Final obj;obj.print(); // 输出 "Derived2"// 通过基类引用访问Base& baseRef = obj;baseRef.print(); // 同样输出 "Derived2"return 0;
}

在这个示例中:

  • Base 是一个基类,Derived1Derived2 都通过虚继承继承自 Base
  • Final 类从 Derived1Derived2 继承,解决了潜在的菱形继承问题。
  • print 方法在 Derived1Derived2 中被覆盖,并在 Final 中再次覆盖。

当然,我可以为多重继承、抽象类和接口提供相应的C++示例。

多重继承

多重继承允许一个类同时继承自多个基类。

示例代码:多重继承

#include <iostream>// 基类1
class Printer {
public:void print() {std::cout << "Printing document" << std::endl;}
};// 基类2
class Scanner {
public:void scan() {std::cout << "Scanning document" << std::endl;}
};// 派生类,从两个基类继承
class MultifunctionMachine : public Printer, public Scanner {};int main() {MultifunctionMachine mfm;mfm.print();  // 调用Printer的成员mfm.scan();   // 调用Scanner的成员return 0;
}

抽象类

抽象类至少包含一个纯虚函数,并且不能直接实例化。

示例代码:抽象类

#include <iostream>// 抽象基类
class Shape {
public:// 纯虚函数virtual void draw() const = 0;
};// 派生类
class Circle : public Shape {
public:void draw() const override {std::cout << "Drawing a circle." << std::endl;}
};int main() {Circle circle;circle.draw();  // 调用派生类的实现// Shape shape; // 错误:不能实例化抽象类return 0;
}

接口

在C++中,接口可以通过完全抽象的类(只有纯虚函数)实现。

示例代码:接口

#include <iostream>// 接口
class Drawable {
public:virtual void draw() const = 0;
};// 实现接口的类
class Rectangle : public Drawable {
public:void draw() const override {std::cout << "Drawing a rectangle." << std::endl;}
};int main() {Rectangle rect;rect.draw();  // 调用具体实现return 0;
}

总结

这次从类的基础知识开始,讲了构造函数、析构函数、以及类的成员变量和方法。

接着,讲了重载构造函数、拷贝构造函数、赋值运算符以及静态成员。

然后讲了继承、多态、友元类和友元函数。

最后模板类的概念,还有一些高级特性的基本概念

万字长文,朋友们点赞、关注啊!!!

相关文章:

c++类全面讲解

文章目录 前言类的基本概念基本结构类与结构体的区别示例代码 类的属性和方法属性&#xff08;成员变量&#xff09;方法&#xff08;成员函数&#xff09;访问修饰符示例代码 类的构造函数和析构函数构造函数析构函数示例代码 类的构造函数重载重载构造函数示例代码 类中的拷贝…...

使用Python和Pygame库创建简单的的彩球效果

简介 Pygame是一款强大的游戏开发库&#xff0c;可以用于创建各种有趣的图形效果。为了更好地了解Pygame的功能&#xff0c;今天我们将要做的是在屏幕上随机生成一些彩色的小球&#xff0c;并使它们以不同的速度和方向移动。当小球碰到屏幕边缘时&#xff0c;它们将反弹。 功能…...

第2课 使用FFmpeg读取rtmp流并用openCV显示视频

本课对应源文件下载链接&#xff1a; https://download.csdn.net/download/XiBuQiuChong/88680079 这节课我们开始利用ffmpeg和opencv来实现一个rtmp播放器。播放器的最基本功能其实就两个:显示画面和播放声音。在实现这两个功能前&#xff0c;我们需要先用ffmpeg连接到rtmp服…...

【中小型企业网络实战案例 七】配置限速

相关学习文章&#xff1a; 【中小型企业网络实战案例 一】规划、需求和基本配置 【中小型企业网络实战案例 二】配置网络互连互通【中小型企业网络实战案例 三】配置DHCP动态分配地址 【中小型企业网络实战案例 四】配置OSPF动态路由协议【中小型企业网络实战案例 五】配置可…...

Hive实战:实现数据去重

文章目录 一、实战概述二、提出任务三、完成任务&#xff08;一&#xff09;准备数据1、在虚拟机上创建文本文件2、上传文件到HDFS指定目录 &#xff08;二&#xff09;实现步骤1、启动Hive Metastore服务2、启动Hive客户端3、基于HDFS数据文件创建Hive外部表4、利用Hive SQL实…...

客户满意度调查常用的ChatGPT通用提示词模板

调查目的与范围&#xff1a;如何明确调查的目的和范围&#xff0c;确保调查的针对性&#xff1f; 调查方法选择&#xff1a;如何选择合适的调查方法&#xff0c;如问卷调查、访谈等&#xff1f; 问卷设计&#xff1a;如何设计问卷&#xff0c;确保问题的针对性和客观性&#…...

Android--Jetpack--Paging详解

不尝世间醋与墨&#xff0c;怎知人间酸与苦。 择一业谋食养命&#xff0c;等一运扭转乾坤。 你见过哪些令你膛目结舌的代码技巧&#xff1f; 文章目录 不尝世间醋与墨&#xff0c;怎知人间酸与苦。择一业谋食养命&#xff0c;等一运扭转乾坤。你见过哪些令你膛目结舌的代码技…...

Unity 基于UDP实现本地时间与网络时间校验 防客户端修改日期作弊

新建一个Unity GameObject 挂上NTPComponent脚本 时间校验 源码 using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using UnityEngine.Networking; using System.Text; using System.Net.Sockets; using System.Net; using Sys…...

ArduPilot开源代码之MatekSys Optical Flow 3901-L0X

ArduPilot开源代码之MatekSys Optical Flow 3901-L0X 1. 源由2. 安装3. 参数配置3.1 配置光流定位3.2 配置激光测距3.3 辅助配置 4. 测试4.1 光流数据测试4.2 测距数据测试4.3 飞行注意事项4.4 实际飞行测试 5. 参考资料 1. 源由 之前介绍过MatekSys Optical Flow 3901-L0X模块…...

【时钟】分布式时钟HLC|Logical Time|Vector Clock|True Time

目录 简略 详细 附录 1 分布式系统不能使用NTP的原因 简略 分布式系统中不同于单机系统不能使用NTP(网络时间协议&#xff08;Network Time Protocol&#xff09;)来获取时间&#xff0c;所以我们需要一个特别的方式来获取分布式系统中的时间&#xff0c;mvcc也是使用time保证读…...

人工智能AI与3D视觉技术的结合正在引领新一代移动机器人的革新

随着科技的飞速发展&#xff0c;人工智能AI与3D视觉技术的结合正在引领新一代移动机器人的革新。富唯智能移动机器人&#xff0c;以其独特的3D视觉技术&#xff0c;赋予了移动机器人一双“智慧之眼”&#xff0c;从而为现代工业自动化带来了前所未有的突破。 富唯智能移动机器…...

NSSCTF 简单包含

开启环境: 使用POST传flag&#xff0c;flag目录/var/www/html/flag.php 先使用post来尝试读取该flag.php 没反应: 查看一下源码index.php&#xff0c;看有什么条件 base64解密: <?php$path $_POST["flag"];if (strlen(file_get_contents(php://input)) <…...

FlinkSQL处理Canal-JSON数据

背景信息 Canal是一个CDC&#xff08;ChangeLog Data Capture&#xff0c;变更日志数据捕获&#xff09;工具&#xff0c;可以实时地将MySQL变更传输到其他系统。Canal为变更日志提供了统一的数据格式&#xff0c;并支持使用JSON或protobuf序列化消息&#xff08;Canal默认使用…...

玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— DevEco Studio下载与安装

一、下载DevEco Studio IDE开发工具 1. 登录鸿蒙官网 网址为&#xff1a; ​​​​​​​华为HarmonyOS智能终端操作系统官网 | 应用设备分布式开发者生态 页面如下&#xff1a; 2. 搜索“DevEco Studio IDE” 点击右上角的“请输入关键词”&#xff0c;在其中搜索“DevEc…...

大模型上下文长度的超强扩展:从LongLora到LongQLora

前言 本文一开始是《七月论文审稿GPT第2版&#xff1a;从Meta Nougat、GPT4审稿到Mistral、LongLora Llama》中4.3节的内容&#xff0c;但考虑到 一方面&#xff0c;LongLora的实用性较高二方面&#xff0c;为了把LongLora和LongQLora更好的写清楚&#xff0c;而不至于受篇幅…...

pdf格式转换为txt格式

pdf文档转换为txt文档 首先在python3虚拟环境中安装PyPDF2 Python 3.6.8 (default, Jun 20 2023, 11:53:23) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux Type "help", "copyright", "credits" or "license" for more infor…...

scss使用for循环遍历,动态赋值类名并配置不同颜色

需求&#xff1a;后端要传入不同的等级&#xff0c;前端通过等级展示不同的字体颜色&#xff0c;通过scss遍历更有利于动态修改颜色或者增删等级 1.通过 for $i from 1 through 4 定义循环&#xff0c;索引值为i 2.nth($colors, $i) 取出对应的颜色 $colors: #ff0000, #00ff…...

GaussDB数据库使用COPY命令导数

目录 一、前言 二、GaussDB数据库使用COPY命令导数语法 1、语法COPY FROM 2、语法COPY TO 3、特别说明及参数示意 三、GaussDB数据库使用COPY命令导数示例 1、操作步骤 2、准备工作&#xff08;示例&#xff09; 3、把一个表的数据拷贝到一个文件&#xff08;示例&…...

SunFMEA软件免费试用:FMEA的目标和限制是什么?

免费试用FMEA软件-免费版-SunFMEA FMEA&#xff0c;即故障模式与影响分析&#xff0c;是一种预防性的质量工具&#xff0c;旨在识别、评估和优先处理潜在的故障模式及其对系统性能的影响。其目标是提高产品和过程的可靠性和安全性&#xff0c;降低产品故障的风险&#xff0c;并…...

【Redis交响乐】Redis中的数据类型/内部编码/单线程模型

文章目录 一. Redis中的数据类型和内部编码二. Redis的单线程模型面试题: redis是单线程模型,为什么效率之高,速度之快呢? 在上一篇博客中我们讲述了Redis中的通用命令,本篇博客中我们将围绕每个数据结构来介绍相关命令. 一. Redis中的数据类型和内部编码 type命令实际返回的…...

APK 瘦身

APK 瘦身的主要原因是考虑应用的下载转化率和留存率&#xff0c;应用太大了&#xff0c;用户可能就不下载了。再者&#xff0c;因为手机空间问题&#xff0c;用户有可能会卸载一些占用空间比较大的应用&#xff0c;所以&#xff0c;应用的大小也会影响留存率。 1 APK 的结构 …...

GitHub上的15000个Go模块存储库易受劫持攻击

内容概要&#xff1a; 目前研究发现&#xff0c;GitHub上超过15000个Go模块存储库容易受到一种名为“重新劫持”的攻击。 由于GitHub用户名的更改会造成9000多个存储库容易被重新劫持&#xff0c;同时因为帐户删除&#xff0c;会对6000多个存储库造成重新劫持的危机。目前统计…...

避免3ds Max效果图渲染一片黑的4个正确解决方法

在进行3ds Max效果图渲染时&#xff0c;有时候会遇到渲染一片黑的情况&#xff0c;这给我们的工作带来了很大的困扰。为了解决这个问题&#xff0c;下面我将介绍4个正确的解决方法。 1.相机位置 首先需要考虑场景内的相机位置是否有问题。如果相机放在了模型的内部或者墙体的外…...

UI演示双视图立体匹配与重建

相关文章&#xff1a; PyQt5和Qt designer的详细安装教程&#xff1a;https://blog.csdn.net/qq_43811536/article/details/135185233?spm1001.2014.3001.5501Qt designer界面和所有组件功能的详细介绍&#xff1a;https://blog.csdn.net/qq_43811536/article/details/1351868…...

添加一个编辑的小功能(PHP的Laravel)

一个编辑的按钮可以弹出会话框修改断更天数 前台 加一个编辑按钮的样式&#xff0c;他的名字是固定好的 之前有人封装过直接用就好&#xff0c;但是一定放在class里面&#xff0c;不要放在id里面 看见不认识的方法一定要去看里面封装的是什么 之前就是没有看&#xff0c;所以…...

YOLOv8改进 | 主干篇 | ConvNeXtV2全卷积掩码自编码器网络

一、本文介绍 本文给大家带来的改进机制是ConvNeXtV2网络,ConvNeXt V2是一种新型的卷积神经网络架构,它融合了自监督学习技术和架构改进,特别是加入了全卷积掩码自编码器框架和全局响应归一化(GRN)层。我将其替换YOLOv8的特征提取网络,用于提取更有用的特征。经过我的实…...

elasticsearch7.17.9两节点集群改为单节点

需求 将数据从node-23-1节点中迁移到node-83-1节点。但是现在node-83-1并没有加入到集群中&#xff0c;因此首先将node-83-1加入到node-23-1的集群 解决方案 使用ES版本为7.17.9&#xff0c;最开始设置集群为一个节点&#xff0c;node-23-1的配置如下 cluster.name: my-app…...

二叉树的层序遍历,力扣

目录 题目地址&#xff1a; 题目&#xff1a; 我们直接看题解吧&#xff1a; 解题方法&#xff1a; 方法分析&#xff1a; 解题分析&#xff1a; 解题思路&#xff1a; 代码实现&#xff1a; 代码补充说明&#xff1a; 题目地址&#xff1a; 102. 二叉树的层序遍历 - 力扣&…...

构建Dockerfile报错/bin/sh: 1: cd: can‘t cd to /xxx/yyy问题记录

目录 关键的命令行 排查分析 原因 附&#xff1a;Dockerfile构建时打印命令输出的办法 关键的命令行 WORKDIR /app COPY record . RUN cd record && xxx 执行到RUN时报了错&#xff1a; /bin/sh: 1: cd: cant cd to /app/record 并且宿主机当前目录也准备好了re…...

Vue常用的修饰符详解(有哪些,怎么用)

文章目录 一、修饰符是什么二、修饰符的作用1.表单修饰符lazytrimnumber 2.事件修饰符stoppreventselfoncecapturepassivenative 3.鼠标按钮修饰符4.键盘修饰符5.v-bind修饰符asyncpropscamel 三、应用场景参考文献 一、修饰符是什么 在程序世界里&#xff0c;修饰符是用于限定…...

做网站设计需要学会哪些/网页设计html代码大全

Jquery中的选择器分为几大类&#xff1a;基本过滤选择器&#xff0c;层次选择器&#xff0c;内容过滤选择器&#xff0c;可见性过滤选择器&#xff0c;属性过滤选择器&#xff0c;子元素过滤选择器&#xff0c;表单对象选择器和表单对象属相过滤选择器。 1.非基本过滤选择器&am…...

在线做插画的网站/2022年十大流行语

1、字符串 定义&#xff1a;它是一个有序的字符的集合&#xff0c;用于存储和表示基本的文本信息&#xff0c;‘’或“”或‘’‘ ’‘’中间包含的内容称之为字符串特性&#xff1a;1.只能存放一个值2.不可变3.按照从左到右的顺序定义字符集合&#xff0c;下标从0开始顺序访问…...

怎么做自己的淘宝网站/站长工具ip地址

本篇文章小编给大家分享一下Java虚拟机内存溢出与内存泄漏代码原理解析&#xff0c;文章代码介绍的很详细&#xff0c;小编觉得挺不错的&#xff0c;现在分享给大家供大家参考&#xff0c;有需要的小伙伴们可以来看看。一、基本概念内存溢出&#xff1a;简单地说内存溢出就是指…...

access 可以做网站不/网站流量查询网站统计查询

ASP.NET 的ViewState是使用Base64的字符串保存在一个隐藏域中的。下面通过一个例子来解析它们 1. 页面<% Page Language"C#" AutoEventWireup"true" CodeBehind"Default.aspx.cs" Inherits"WebApp._Default" %><!DOCTYPE htm…...

电子商务网站建设资料/安徽百度seo公司

...

源码做网站教程/百度推广优化技巧

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼最近学习CUDA C的编程&#xff0c;在并行运行一个简单的解调算法的时候&#xff0c;统计时间后发现运行速度越来越慢(但还是运算结果正确的)&#xff0c;后来简化到只运行其中一个核函数的时候&#xff0c;就算复杂度下降了&#x…...