C++类与对象深度解析:从基础到应用
目录:
- 1. 类的基本概念与定义
- 1.1 类的定义与访问限定符
- 1.2 实例化与对象内存布局
- 1.3 this指针
- 2.类的默认成员函数
- 2.1 构造函数与析构函数详解
- 构造函数
- 析构函数
- 2.2 拷贝构造函数
- 2.3 赋值运算符重载
- 运算符重载
- 3. 初始化列表
- 4.类型转换
- 5. 静态成员
- 6.友元和内部类
- 6.1 友元
- 6.2 内部类
- 总结
1. 类的基本概念与定义
1.1 类的定义与访问限定符
类是C++封装数据与行为的核心单元,通过class
或struct
定义:
class Stack
{
public: // 公有成员,外部可访问void Push(int x);
private: // 私有成员,仅类内访问int* _array; // 成员变量习惯加前缀_或msize_t _top;
};
- 访问限定符:
public
:类外可直接访问。private
/protected
:类外不可直接访问(默认class
为private
,struct
为public
)。
1.2 实例化与对象内存布局
实例化即分配内存(满足内存对齐)创建对象,对象大小仅包含成员变量(成员函数存于代码段):
Stack st; // 实例化对象
cout << sizeof(st); // 输出对象大小(不含函数)
- 空类大小:空类对象占1字节,标识存在性。
为什么不算成员函数呢?
每一个对象都是独立的个体,有自己的私有属性(身高、体重、大小…),正是这些私有属性所以每个对象都是独一无二的不是吗?而成员函数除了传的参数不一样,实现功能都是一样的,如果每一个对象里面都包含功能一样的函数是不是有点浪费空间了呢,因此成员函数都是放在公共的空间里的,不在对象的空间里
成员函数声明和定义可以分开写
class A
{public:void print();//声明private:}void A::print()
{}
形象的理解:类就是个蓝图,对象就是根据蓝图创建出来的具体的房子
1.3 this指针
class Date
{
public:void print(){cout << _year <<"/"<<_month<<"/"<<_day << endl;}private:int _year;int _month;int _day;
};
假设这里有两个Date类型的对象d1、d2,当我们去调用print这个成员函数时,它怎么知道我们要访问的是那个对象里成员变量?
- 隐含参数:定义在类里的成员函数都隐藏了一个
this指针
,实际接收ClassName* const this
参数,C++规定不能在实参和形参的位置显示的写this指针
(编译时编译器会处理),但是可以在函数体内显示使⽤this指针
。 - 访问成员:
_year
等价于this->_year
。
class Date
{
public://void print(Date* const this)void print(){cout << _year <<"/"<<_month<<"/"<<_day << endl;// cout <<this-> _year <<"/"<<tjos->_month<<"/"<<this->_day << endl;}private:int _year;int _month;int _day;
};int main()
{Date d1;d1.print();//实际上为d1.print(&d1);
}
2.类的默认成员函数
默认成员函数就是用户没有显式实现,编译器会自动动生成的成员函数称为默认成员函数。⼀个类,我们不写的情况下编译器会默认生成以下6个默认成员函数,需要注意的是这6个中最重要的是前4个,最后两个取地址重载不重要,我们稍微了解⼀下即可。(C++11后还有两个)
2.1 构造函数与析构函数详解
构造函数
-
作用:替代
Init
函数,初始化对象(非分配内存)。 -
特点:
- 与类同名、无返回值、支持重载。
- 默认构造函数:用户未定义时编译器生成(对内置类型不初始化或者初始化为0,不同的编译器不同;对于自定义类型成员变量,要求调用这个成员变量的默认构造函数初始化。如果这个成员变量,没有默认构造函数,那么就会报错,我们要初始化这个成员变量,需要用初始化列表才能解决,初始化列表)。 默认构造函数包括:无参的,全缺省的,编译器自动生成的,三种只能存在一种,总结⼀下就是不传实参就可以调用的构造就叫默认构造
- 对象实例化后,系统会自动调用对应的构造函数
:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的原生数据类型,
如:int/char/double/指针等,自定义类型就是我们使用class/struct等关键字自己定义的类型。
class Date {
public:Date() // 无参构造{_year = 2024; } Date(int year = 2024, int month = 4, int day = 26)//全缺省{_year = year;_month = month;_day = day;}//编译器自动生成......Date(int year, int month, int day) // 带参构造{ _year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}private:int _year, _month, _day;
};int main()
{
// 如果留下三个构造中的第⼆个带参构造,第⼀个和第三个注释掉
// 编译报错:error C2512: “Date”: 没有合适的默认构造函数可⽤Date d1; // 调⽤默认构造函数Date d2(2025, 1, 1); // 调⽤带参的构造函数
// 注意:如果通过⽆参构造函数创建对象时,对象后⾯不⽤跟括号,否则编译器⽆法
// 区分这⾥是函数声明还是实例化对象
// warning C4930: “Date d3(void)”: 未调⽤原型函数(是否是有意⽤变量定义的?)Date d3();d1.Print();d2.Print();
return 0;
}
析构函数
- 作用:清理资源(如释放堆内存)。
- 特点:
- 名为
~ClassName
,无参数、不可重载。若未显式定义,系统会自动生成默认的析构函数(编译器自动生成的析构函数对内置类型成员不做处理,自定类型成员会调用他的析构函数) - 对象生命周期结束时自动调用(如局部对象离开作用域)。
- 名为
#include<iostream>
using namespace std;
typedef int STDataType;
class Stack
{
public:Stack(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}~Stack(){cout << "~Stack()" << endl;free(_a);_a = nullptr;_top = _capacity = 0;}
private:STDataType* _a;size_t _capacity;size_t _top;
};
// 两个Stack实现队列
class MyQueue
{
public:
//编译器默认⽣成MyQueue的析构函数调⽤了Stack的析构,释放的Stack内部的资源
// 显⽰写析构,也会⾃动调⽤Stack的析构
/*~MyQueue()
{}*/
private:Stack pushst;Stack popst;
};
int main()
{Stack st;MyQueue mq;return 0;
}
2.2 拷贝构造函数
如果⼀个构造函数的第⼀个参数是自身类类型的引用,且任何额外的参数都有默认值,则此构造函数也叫做拷贝构造函数,也就是说拷贝构造是⼀个特殊的构造函数。
- 场景:值传递自定义类型参数时,值返回自定义类型对象时
- 特点:
- 构造函数的重载形式,参数必须为本类对象的引用(可搭配其他带默认值的参数)
- 未显式定义时,编译器自动生成:
- 内置类型 → 浅拷贝(值复制)
- 自定义类型 → 调用其拷贝构造
有时候浅拷贝可以完成我们的需求,但是如果是Stack这种不显示写,会自动实现浅拷贝,而导致一些错误
#include<iostream>
using namespace std;
typedef int STDataType;
class Stack
{
public:Stack(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}//显示写拷贝构造Stack(const Stack& st){// 需要对_a指向资源创建同样⼤的资源再拷贝值_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);if (nullptr == _a){perror("malloc申请空间失败!!!");return;}memcpy(_a, st._a, sizeof(STDataType) * st._top);_top = st._top;_capacity = st._capacity;
}~Stack(){cout << "~Stack()" << endl;free(_a);_a = nullptr;_top = _capacity = 0;}
private:STDataType* _a;size_t _capacity;size_t _top;
};// 两个Stack实现队列
class MyQueue
{
public:
private:Stack pushst;Stack popst;
};
int main()
{Stack st1;// Stack不显⽰实现拷贝构造,⽤⾃动⽣成的拷贝构造完成浅拷贝// 会导致st1和st2⾥⾯的_a指针指向同⼀块资源,析构时会析构两次,程序崩溃Stack st2 = st1;MyQueue mq1;// MyQueue⾃动⽣成的拷贝构造,会⾃动调⽤Stack拷贝构造完成pushst/popst// 的拷贝,只要Stack拷贝构造⾃⼰实现了深拷贝,他就没问题MyQueue mq2 = mq1;return 0;
}
为什么第一个参数要用引用呢?
注意:Stack st2(st1) ;和Stack st2 = st1;这样写本质是一样的,看下面的汇编代码
使用建议:
- 无资源管理(如Date类)→ 直接用自动生成的
- 有动态资源(如Stack类数组)→ 必须显式深拷贝
- 含自定义类型成员(如MyQueue含Stack)→ 自动调用其拷贝构造
- 显式写了析构函数释放资源 → 必须显式实现拷贝构造
2.3 赋值运算符重载
- 场景:作用于两个已存在的对象,完成内容复制(拷贝构造是初始化新对象)
- 特点
-
语法特点 :
- 必须定义为成员函数,参数为
const 类名&
(建议这样写,使用引用避免传值传参会有拷贝,带默认值需用const
修饰) - 返回值建议类引用:支持连续赋值(如
a = b = c
),提高效率
- 必须定义为成员函数,参数为
-
未显式定义时,编译器自动生成:
- 内置类型 → 浅拷贝(逐字节复制)
- 自定义类型 → 调用其赋值运算符重载
-
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){cout << " Date(const Date& d)" << endl;_year = d._year;_month = d._month;_day = d._day;}
// 传引⽤返回减少拷贝
// d1 = d2;Date& operator=(const Date& d){// 不要检查⾃⼰给⾃⼰赋值的情况if (this != &d){_year = d._year;_month = d._month;_day = d._day;}// d1 = d2表达式的返回对象应该为d1,也就是*thisreturn *this;
}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(2024, 7, 5);Date d2(d1);Date d3(2024, 7, 6);d1 = d3;// 需要注意这⾥是拷贝构造,不是赋值重载// 请牢牢记住赋值重载完成两个已经存在的对象直接的拷贝赋值// ⽽拷贝构造⽤于⼀个对象拷贝初始化给另⼀个要创建的对象
Date d4 = d1;
return 0;
}
使用建议
- 无需显式实现:
- 成员全为内置类型且无资源管理(如
Date
类) - 含自定义类型成员(如
MyQueue
含Stack
)→ 自动调用其赋值重载
- 成员全为内置类型且无资源管理(如
- 必须显式深拷贝:
- 有动态资源(如
Stack
类数组) - 若显式写了析构函数 → 必须配套自定义赋值重载(避免内存泄漏)
- 有动态资源(如
与拷贝构造区别
- 拷贝构造:对象初始化时由另一个对象创建
- 赋值重载:两个已存在对象赋值时覆盖旧值
总结:处理对象赋值用 operator=
,默认浅拷贝,深资源需手动重载,返回值用引用效率高。
Stack& operator=(const Stack& st) {if (this != &st) {free(_array); // 释放旧资源_array = (int*)malloc(/*...*/); // 深拷贝新资源// 其他成员赋值...}return *this; // 支持连续赋值
}
运算符重载
当运算符作用于类类型的运算对象时,可以通过运算符重载重新定义该运算符的含义。
例如:我们前面讲过的<<
和>>
运算符,在C语言中是移位运算符,而在C++中可以作为输出和输入使用。
运算符重载函数跟普通函数一样有参数、返回值类型、函数体,不同的是由关键字operator
和其后面要定义的运算符共同组成
返回值类型 operator运算符(参数)
{.............
}
- 重载运算符函数的参数数量与该运算符作用的运算对象数量一样多。一元运算符(+、-、!、++、–、&……)有一个参数;二元运算符(+、-、%、*……)有两个参数,对于二元运算符,左侧的运算对象会传递给第一个参数,右侧的运算对象会传递给第二个参数。
当一个运算符重载函数作为成员函数时,左侧的运算对象会传递给隐藏的
this指针
,也就是说作为成员函数时,运算符重载函数显示的参数数量比运算对象的数量少一个
- 运算符重载函数要么是类的成员,要么至少有一个类类型的参数,对于内置类型的运算对象重载没有意义
- 只能重载已有的运算符,无权创造新的运算符。以下几个运算符不可以重载:
::、.*、.、?:
- 重载运算符的优先级与结合性与对应的内置运算符保持一致
使用:
int main()
{Date d1;Date d2;非成员函数的等价调用d1 + d2;operator+(d1,d2);成员函数的等价调用d1 + d2;d1.operator(d2);}
以下是一个日期类的实现:
#include <iostream>
#include <assert.h>
using namespace std;class Date
{
public:Date(int year = 2025, int month = 4, int day = 24);/*Date():_year(2025),_month(4),_day(27){}*/void print(){cout << _year << "/" << _month << "/" << _day << endl;}//日期比较bool operator<(const Date& d)const;bool operator==(const Date& d)const;bool operator<=(const Date& d)const;bool operator>(const Date& d)const;bool operator>=(const Date& d)const;bool operator!=(const Date& d)const;int GetMonthDays(int year, int month)const{assert(month > 0 && month < 13);static int daysArry[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//判断闰年if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){return 29;}else{return daysArry[month];}}//日期+天数->日期Date& operator+=(int day);Date operator+(int day)const;//日期-天数->日期Date& operator-=(int day);Date operator-(int day)const;//日期-日期->天数int operator-(const Date& d)constprivate:int _year = 2025;int _month = 4;int _day = 26;
};Date::Date(int year , int month, int day )
{if (month > 0 && month < 13 && day > 0 && day <= GetMonthDays(year, month)){_year = year;_month = month;_day = day;}else{cout << "日期非法" << endl;}
}bool Date::operator<(const Date& d)const
{if (_year < d._year){return true;}else if ((_year == d._year) && (_month < d._month)){return true;}else if((_year == d._year) && (_month == d._month)&&(_day < d._day)){return true;}return false;
}bool Date::operator==(const Date& d)const
{return _year == d._year && _month == d._month && _day == d._day;
}//复用
bool Date::operator<=(const Date& d)const
{return *this < d || *this == d;
}
bool Date::operator>(const Date& d)const
{return !(*this <= d);
}
bool Date::operator>=(const Date& d)const
{return !(*this < d);
}
bool Date::operator!=(const Date& d)const
{return !(*this == d);
}Date& Date::operator+=(int day)
{if (day < 0){return *this -= (-day); // 负数转为减法}_day += day;while (_day > GetMonthDays(_year, _month)){_day -= GetMonthDays(_year, _month);_month++;if (_month == 13){_month = 1;_year++;}}return *this;
}Date Date::operator+(int day)const
{Date tmp(*this);tmp += day;return tmp;
}Date& Date::operator-=(int day)
{if (day < 0){return *this += (-day); // 负数转为加法}_day -= day;while (_day <= 0){_month--;if (_month == 0){_month = 12;_year--;}_day += GetMonthDays(_year, _month);}return *this;
}Date Date::operator-(int day)const
{Date tmp(*this);tmp -= day;return tmp;
}int Date::operator-(const Date& d)const
{int flag = 1;Date max = (*this);Date min = d;if (max < min){max = d;min = (*this);flag = -1;}int n = 0;while (min != max){++min;++n;}return n * flag;
}
const成员函数
- 作用:承诺不修改对象状态。
- 语法:
void Print() const { ... }
。
跟前面引用一样,如果用const
修饰一个对象,也会有访问权限放大的问题,并且作为成员函数,this指针
是隐藏的不准在函数参数显示写,而且默认是没有被const
修饰的,于是我们的祖师爷就发明了在后面加const
的语法,代表修饰的是this指针
3. 初始化列表
- 构造函数除了用函数体赋值还可以使用初始化列表,初始化列表的使用方式是以⼀个冒号开始,接着是⼀个以逗号分隔的数据成员列表,每个"成员变量"后面跟⼀个放在括号中的初始值或表达式。
- 每个成员变量在初始化列表中只能出现⼀次,语法理解上初始化列表可以认为是每个成员变量定义初始化的地方。
- 初始化列表中按照成员变量在类中声明顺序进行初始化,跟成员在初始化列表出现的的先后顺序无关。建议声明顺序和初始化列表顺序保持⼀致。
- 初始化列表总结:
- 无论是否显示写初始化列表,每个构造函数都有初始化列表;
- 无论是否在初始化列表显示初始化成员变量,每个成员变量都要走初始化列表初始化;
#include<iostream>
using namespace std;
class Time
{
public:Time(int hour):_hour(hour){cout << "Time()" << endl;}
private:int _hour;
};
class Date
{
public:Date(int& x, int year = 1, int month = 1, int day = 1):_year(year),_month(month),_day(day),_t(12),_ref(x),_n(1){// error C2512: “Time”: 没有合适的默认构造函数可⽤// error C2530 : “Date::_ref” : 必须初始化引⽤// error C2789 : “Date::_n” : 必须初始化常量限定类型的对象}
void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;Time _t; // 没有默认构造int& _ref; // 引⽤const int _n; // const
};
int main()
{int i = 0;Date d1(i);d1.Print();return 0;
}
#include<iostream>
using namespace std;
class Time
{
public:Time(int hour):_hour(hour){cout << "Time()" << endl;}
private:int _hour;
};class Date
{
public:Date():_month(2){cout << "Date()" << endl;}void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private:// 注意这⾥不是初始化,这⾥给的是缺省值,这个缺省值是给初始化列表的// 如果初始化列表没有显⽰初始化,默认就会⽤这个缺省值初始化int _year = 1;int _month = 1;int _day;Time _t = 1;const int _n = 1;int* _ptr = (int*)malloc(12);
};int main()
{Date d1;d1.Print();return 0;
}
4.类型转换
- C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数。
- 构造函数前面加explicit就不再支持隐式类型转换。
- 类类型的对象之间也可以隐式转换,需要相应的构造函数支持
#include<iostream>
using namespace std;
class A
{
public:// 构造函数explicit就不再⽀持隐式类型转换// explicit A(int a1)A(int a1):_a1(a1){}//explicit A(int a1, int a2)A(int a1, int a2):_a1(a1), _a2(a2){}void Print(){cout << _a1 << " " << _a2 << endl;}int Get() const{return _a1 + _a2;}
private:int _a1 = 1;int _a2 = 2;
};class B
{
public:B(const A& a):_b(a.Get()){}
private:int _b = 0;
};
int main()
{// 1构造⼀个A的临时对象,再⽤这个临时对象拷⻉构造aa3// 编译器遇到连续构造+拷⻉构造->优化为直接构造A aa1 = 1;aa1.Print();const A& aa2 = 1;// C++11之后才⽀持多参数转化A aa3 = { 2,2 };// aa3隐式类型转换为b对象// 原理跟上⾯类似B b = aa3;const B& rb = aa3;return 0;
}
5. 静态成员
- 静态变量:类内声明,类外初始化,所有对象共享。
class Counter
{
public:static int count; // 声明
};
int Counter::count = 0; // 初始化(不受访问限定符限制)
- 静态函数:无
this
指针,仅能访问静态成员。 (非静态的成员函数,可以访问任意的静态成员变量和静态成员函数。)
static int GetCount() { return count; }
- 突破类域就可以访问静态成员,可以通过类名::静态成员 或者对象.静态成员 来访问静态成员变量和静态成员函数。(静态成员也是类的成员,受public、protected、private 访问限定符的限制。)
// 实现⼀个类,计算程序中创建出了多少个类对象?
#include<iostream>
using namespace std;
class A
{
public:A(){++_scount;}A(const A& t){++_scount;}~A(){--_scount;}static int GetACount(){return _scount;}
private:// 类⾥⾯声明static int _scount;
};
// 类外⾯初始化
int A::_scount = 0;int main()
{cout << A::GetACount() << endl;A a1, a2;A a3(a1);cout << A::GetACount() << endl;cout << a1.GetACount() << endl;// 编译报错:error C2248: “A::_scount”: ⽆法访问 private 成员(在“A”类中声明)//cout << A::_scount << endl;return 0;
}
6.友元和内部类
6.1 友元
-
定义:用
friend
声明,可访问类的私有/保护成员,突破封装(慎用) -
分类:
- 友元函数:普通函数声明为类友元
class Date {friend void PrintDate(const Date& d); // 声明友元
private:int _year;
};
void PrintDate(const Date& d) {cout << d._year; // 访问私有成员
}
- 友元类:整个类声明为另一个类的友元
//class B可访问class A的所有成员
class A {friend class B; // B是A的友元类
private:int _secret;
-
友元函数特点:
- 非成员函数,但能访问类私有数据
- 声明位置不限(类内任意处)
- 支持多类共享(可作多个类的友元)
-
友元类特点:
- 友元类的所有成员函数均可访问目标类私有数据
- 单向关系(A是B友元 ≠ B是A友元)
- 不可传递(A友元的友元 ≠ A的友元)
友元是C++开后门的钥匙,用friend
声明可跨权限访问,便利但破坏封装,慎用为妙。
6.2 内部类
-
本质
- 嵌套封装:定义在另一个类内部的独立类,本质是类的逻辑封装手段。
-
特点
- 受外部类作用域和访问权限(如
private/protected
)限制 - 外部类对象不包含内部类对象(独立存在)
- 受外部类作用域和访问权限(如
-
访问关系
- 内部类默认是外部类的友元类 → 可访问外部类私有成员
- 外部类不能直接访问内部类私有成员(除非声明友元)
-
适用场景
- A类与B类强关联,且A类仅服务于B类时(如链表节点
Node
作为链表List
的内部类) - 通过
private/protected
声明→ 专属内部类(仅限外部类或子类使用)
- A类与B类强关联,且A类仅服务于B类时(如链表节点
-
权限控制
- 内部类放在
public
区 → 允许外部代码创建实例 - 放在
private
区 → 仅限外部类内部使用
- 内部类放在
内部类是C++中嵌套设计的工具,通过封装和权限控制实现专属协作,需权衡封装性与灵活性。
总结
C++类与对象通过封装、构造/析构、拷贝控制等机制,提供了强大的面向对象能力。深入理解this
指针、静态成员、初始化列表等高级特性,能够写出高效且安全的代码。通过对比C与C++的实现,更能体会面向对象的优势。实践中需警惕浅拷贝、内存泄漏等陷阱。
相关文章:
C++类与对象深度解析:从基础到应用
目录: 1. 类的基本概念与定义1.1 类的定义与访问限定符1.2 实例化与对象内存布局1.3 this指针 2.类的默认成员函数2.1 构造函数与析构函数详解构造函数析构函数 2.2 拷贝构造函数2.3 赋值运算符重载运算符重载 3. 初始化列表4.类型转换5. 静态成员6.友元和内部类6.1…...
JGQ611Ⅱ数据采集电除雾器实验装置
JGQ611Ⅱ数据采集电除雾器实验装置 一.实验目的 1.掌握电除雾器的结构特征与工作原理。 2.测定风压、风速、电压、电流板间距等因素对酸雾去除效率的影响。 3.测定电除雾器的工作效率。 二.技术指标 1.电场电压:0~20KV(可调)。 2.…...
如何判断cgroup的版本?
在 Linux 系统中,判断当前使用的 cgroup 版本(v1 还是 v2)可以通过以下几种方法: 方法一:查看挂载点(最直接) mount | grep cgroup输出分析 cgroups v1:存在多个以 cgroup 开头的…...
基于 Spark 和 Hadoop 的空气质量数据分析与预测系统
基于 Spark 和 Hadoop 的空气质量数据分析与预测系统 文章目录 基于 Spark 和 Hadoop 的空气质量数据分析与预测系统引言项目目标技术栈数据来源系统核心功能1. 用户认证与管理2. 数据总览3. 空气质量分析4. 词云图5. AQI 预测 项目结构预览关键代码分享1. Flask 主文件&#x…...
qt csv文件写操作
实例1: QStringList header; header << "1" << "2"; QStringList footer; footer << "Here is a footer"; QStringList strList; strList << "one" << "two" <&l…...
Java 反射
反射 反射的概述 获取class对象的三种方式 代码实现 package myreflect1;public class MyReflectDemo1 {public static void main(String[] args) throws ClassNotFoundException {//1.第一种方式//全类名:包名类名//最为常用Class clazz1 Class.forName("…...
Spring-使用Java的方式配置Spring
目录 前言 一、使用Java配置Spring 前言 使用纯Java的配置方式,在SpringBoot中随处可见,是必须要学习的 一、使用Java配置Spring 配置Spring有多种方式,我们现在要完全不使用Spring的xml配置了,全权交给Java来做! J…...
cudaMalloc函数说明
cudaMalloc函数说明 cudaError_t cudaMalloc(void** devPtr, size_t size);参数说明 devPtr (输出参数): 类型为 void**,即指向指针的指针。函数执行成功后,*devPtr 将被赋值为 GPU 内存的起始地址。例如:若分配一个 float 数组,需…...
路由协议(静态路由、RIP、OSPF、BGP)
目录 静态路由 RIP OSP BGP 总结 静态路由 定义:由网络管理员手动配置的路由。它不会自动更新,除非管理员手动修改。 特点: 简单:配置简单,适合小型网络。安全:不会与其他路由器交换路由信息&#x…...
基于 HTML5 的贪吃蛇小游戏实现
一、引言 在 Web 开发的世界中,利用 HTML、CSS 和 JavaScript 构建有趣的互动游戏是一项充满乐趣和挑战的任务。本文将详细介绍一个基于 HTML5 的贪吃蛇小游戏的实现过程,通过对代码的解析,带你了解如何打造一个经典的贪吃蛇游戏,…...
学习Linux的第二天
如何在Linux环境下做开发 Linux的一些基操 Tips:平常最表层的是命令行模式,最多见这个默认叫做命令行模式 Vi操作是什么意思呢 就是在提示符输入vi a.c 是可以创建一个a.c这个文件并进入这个输入模式 按i可以输入代码 要退出的时候按esc 再按:(冒号…...
rollout 是什么:机器学习(强化学习)领域
rollout 是什么:机器学习(强化学习)领域 指从特定初始状态开始,按照某个策略或模型进行一系列动作和状态转移,直到达到终止状态或预定时间步数 。比如: 迷宫任务:强化学习代理在迷宫中,从起始点出发,按某策略(如随机选方向走)进行移动,直到找到出口或达到最大移动…...
MATLAB人工大猩猩部队GTO优化CNN-LSTM多变量时间序列预测
本博客来源于CSDN机器鱼,未同意任何人转载。 更多内容,欢迎点击本专栏目录,查看更多内容。 目录 0 引言 1 数据准备 2 CNN-LSTM模型搭建 3 GTO超参数优化 3.1 GTO函数极值寻优 3.2 GTO优化CNN-LSTM超参数 3.3 主程序 4 结语 0 引言…...
android-ndk开发(3): 连接设备到开发机
android-ndk开发(3): 连接设备到开发机 2025/05/05 1. 术语解释 用来写代码的电脑, 我叫做开发机。 我打心底认为 Windows, Linux, macOS 都是 PC, 但是有些人不这么认为, 那就还是叫开发机。 android 手机能运行 app(众所周知…...
谷歌最新推出的Gemini 2.5 Flash人工智能模型因其安全性能相较前代产品出现下滑
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
Kubernetes排错(七)-节点排错
1、节点 Crash 与 Vmcore 分析 kdump 介绍 目前大多 Linux 发新版都会默认开启 kdump 服务,以方便在内核崩溃的时候, 可以通过 kdump 服务提供的 kexec 机制快速的启用保留在内存中的第二个内核来收集并转储内核崩溃的日志信息(vmcore 等文件), 这种机制需要服务…...
《架构安全原则》解锁架构安全新密码
The Open Group最新发布的《架构安全原则》标准中文版为企业架构、技术架构、解决方案架构以及安全架构领域的专业人员提供了一套系统化、可落地的安全设计准则。这一权威文件旨在帮助组织在数字化转型的复杂环境中构建既安全又敏捷的架构体系,其内容与TOGAF标准、N…...
生物化学笔记:神经生物学概论10 运动节律的控制 运动时脑内活动 运动系统疾病及其治疗(帕金森、亨廷顿)
运动节律的控制 运动时脑内活动 运动系统疾病及其治疗 口服多巴胺无法穿越“血脑屏障”,进不到脑子里去,其前体(原材料)能进入血脑屏障。一直吃药,机体会偷懒。另一方面,会影响脑子其他部分。 损毁也只能暂时解决,黑质…...
DDR在PCB布局布线时的注意事项及设计要点
一、布局注意事项 控制器与DDR颗粒的布局 靠近原则:控制器与DDR颗粒应尽量靠近,缩短时钟(CLK)、地址/控制线(CA)、数据线(DQ/DQS)的走线长度,减少信号延迟差异。 分组隔…...
Paramiko源码深入解析
Paramiko是一个基于Python的SSHv2协议实现库,支持远程命令执行、文件传输(SFTP)和安全隧道功能。以下是对其源码的深入解析,涵盖核心模块、关键流程及实现细节。 1. 核心模块与结构 Paramiko的源码结构围绕SSH协议的各个层次设计…...
音频感知动画新纪元:Sonic让你的作品更生动
前言 在现代肖像动画领域,如何精准地控制画面中的焦点,确保声音和画面完美契合,已成为了一个十分值得探索的话题。于是,Sonic 方法应运而生,这种创新的音频感知技术,旨在让肖像动画中的焦点能够与音频内容同步,从而提升整体的沉浸感和表现力。在ComfyUI 中实现这一功能…...
uniapp开发06-视频组件video的使用注意事项
uniapp开发-视频组件video的使用注意事项!实际项目开发中,经常会遇到视频播放的业务需求。下面简单讲解一下,uniapp官方提供的视频播放组件video的常见参数和实际效果。 1:先看代码: <!--视频组件的使用展示-->…...
英伟达语音识别模型论文速读:Fast Conformer
Fast Conformer:一种具有线性可扩展注意力的高效语音识别模型 一、引言 Conformer 模型因其结合了深度可分离卷积层和自注意力层的优势,在语音处理任务中取得了出色的性能表现。然而,Conformer 模型存在计算和内存消耗大的问题,…...
利用jQuery 实现多选标签下拉框,提升表单交互体验
在 Web 开发中,表单设计常常需要支持用户选择多个选项的场景。传统的多选框或下拉菜单在处理大量选项时,可能会影响界面美观和操作便捷性。这时,多选标签下拉框就成为了一种优雅的解决方案。本文将详细介绍如何通过 HTML、CSS 和 jQuery 实现…...
基于 HTML 和 CSS 实现的 3D 翻转卡片效果
一、引言 在网页设计中,为了增加用户的交互体验和视觉吸引力,常常会运用一些独特的效果。本文将详细介绍一个基于 HTML 和 CSS 实现的 3D 翻转卡片效果,通过对代码的剖析,让你了解如何创建一个具有立体感的卡片,在鼠标…...
【阿里云大模型高级工程师ACP学习笔记】2.9 大模型应用生产实践 (下篇)
特别说明:由于这一章节是2025年3月官方重点更新的部分,新增内容非常多,因此我不得不整理成上、下两篇,方便大家参考。 学习目标 备考阿里云大模型高级工程师ACP认证的这部分内容,旨在深入理解大模型应用在安全合规方面的要求,掌握模型部署相关要点,提升实际操作和应对复…...
MVC、MVP、MVVM三大架构区别
1、MVC架构 M(Model):主要处理数据的存储、获取、解析。 V(View):即Fragement、Activity、View等XML文件 C(Controller):主要功能为控制View层数据的显示,…...
期末代码Python
以下是 学生信息管理系统 的简化版代码示例(控制台版本,使用文件存储数据),包含核心功能: 1. 定义学生类 class Student: def __init__(self, sid, name, score): self.sid sid # 学号 self.name name # 姓名 self.s…...
ecat总线6000段定义
1ecat总线 不适合新手学习,我复习用的。 can和ecat是一家的,就跟C和C的关系。 参考CIA402定义 2 PDOr⬇️ 主站发送到终端伺服。 有4组,0x1600 3 PDOt⬆️ 伺服驱动器发送到主站。 我记得有4组,但这款伺服只有2组。 4 速度模…...
数据管理能力成熟度评估模型(DCMM)全面解析:标准深度剖析与实践创新
文章目录 一、DCMM模型的战略价值与理论基础1.1 DCMM的本质与战略定位1.2 DCMM的理论基础与创新点 二、DCMM模型的系统解构与逻辑分析2.1 八大能力域的有机关联与系统架构2.2 五级成熟度模型的内在逻辑与演进规律 三、DCMM八大能力域的深度解析与实践创新3.1 数据战略ÿ…...
Python精进系列:random.uniform 函数的用法详解
目录 🔍 一、引言📌 二、函数定义与参数说明✅ 函数定义⚙️ 参数说明 🧪 三、使用示例1️⃣ 生成单个随机数2️⃣ 生成多个随机数3️⃣ 生成二维坐标 🎯 四、应用场景🧪 模拟实验📊 数据采样🎮…...
观察者模式(Observer Pattern)
🧠 观察者模式(Observer Pattern) 观察者模式是一种行为型设计模式。它定义了一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。通常用于事件驱动的编程场景中。 &am…...
【论文阅读】Joint Deep Modeling of Users and Items Using Reviews for Recommendation
Joint Deep Modeling of Users and Items Using Reviews for Recommendation 题目翻译:利用评论对用户和项目进行联合深度建模进行推荐 原文地址:点这里 关键词: DeepCoNN、推荐系统、卷积神经网络、评论建模、协同建模、评分预测、联合建模…...
webpack 的工作流程
Webpack 的工作流程可以分为以下几个核心步骤,我将结合代码示例详细说明每个阶段的工作原理: 1. 初始化配置 Webpack 首先会读取配置文件(默认 webpack.config.js),合并命令行参数和默认配置。 // webpack.config.js…...
Linux 常用指令详解
Linux 操作系统中有大量强大的命令行工具,下面我将分类介绍一些最常用的指令及其用法。 ## 文件与目录操作 ### 1. ls - 列出目录内容 ls [选项] [目录名] 常用选项: - -l:长格式显示(详细信息) - -a:显…...
DXFViewer进行中 : ->封装OpenGL -> 解析DXF直线
DXFViewer进行中,目标造一个dxf看图工具。. 目标1:封装OpenGL,实现正交相机及平移缩放功能 Application.h #pragma once #include <string> #include <glad/glad.h> #include <GLFW/glfw3.h> #include "../Core/TimeStamp.h" #includ…...
多序列比对软件MAFFT介绍
MAFFT(Multiple Alignment using Fast Fourier Transform)是一款广泛使用且高效的多序列比对软件,由日本京都大学的Katoh Kazutaka等人开发,最早发布于2002年,并持续迭代优化至今。 它支持从几十条到上万条核酸或蛋白质序列的快速比对,同时在准确率和计算效率之间提供灵…...
基于 HTML5 Canvas 实现图片旋转与下载功能
一、引言 在 Web 开发中,经常会遇到需要对图片进行处理并提供下载功能的需求。本文将深入剖析一段基于 HTML5 Canvas 的代码,该代码实现了图片的旋转(90 度和 180 度)以及旋转后图片的下载功能。通过对代码的解读,我们…...
学习路线(机器人系统)
机器人软件/系统学习路线(从初级到专家) 初级阶段(6-12个月)基础数学编程基础机器人基础概念推荐资源 中级阶段(1-2年)机器人运动学机器人动力学控制系统感知系统推荐资源 高级阶段(2-3年&#…...
基于EFISH-SCB-RK3576工控机/SAIL-RK3576核心板的网络安全防火墙技术方案(国产化替代J1900的全栈技术解析)
基于EFISH-SCB-RK3576/SAIL-RK3576的网络安全防火墙技术方案 (国产化替代J1900的全栈技术解析) 一、硬件架构设计 流量处理核心模块 多核异构架构: 四核Cortex-A72(2.3GHz):处理深度…...
基于 jQuery 实现复选框全选与选中项查询功能
在 Web 开发中,复选框是常见的交互元素,尤其是在涉及批量操作、数据筛选等场景时,全选功能和选中项查询功能显得尤为重要。本文将介绍如何使用 HTML、CSS 和 jQuery 实现一个具备全选、反选以及选中项查询功能的复选框组,帮助开发…...
Python中的JSON库,详细介绍与代码示例
目录 1. 前言 2. json 库基本概念 3. json 的适应场景 4. json 库的基本用法 4.1 导 json入 模块 4.2 将 Python 对象转换为 JSON 字符串 4.3 将 JSON 字符串转换为 Python 对象 4.4 将 Python 对象写入 JSON 文件 4.5 从 JSON 文件读取数据 4.6 json 的其他方法 5.…...
tensorflow 调试
tensorflow 调试 tf.config.experimental_run_functions_eagerly(True) 是 TensorFlow 中的一个配置函数,它的作用是: 让 tf.function 装饰的函数以 Eager 模式(即时执行)运行,而不是被编译成图(Graph&…...
iptables的基本选项及概念
目录 1.按保护范围划分: 2.iptables 的基础概念 4个规则表: 5个规则链: 3.iptables的基础选项 4.实验 1.按保护范围划分: 主机防火墙:服务范围为当前一台主机 input output 网络防火墙:服务范围为防…...
使用AI 将文本转成视频 工具 介绍
🎬 文字生成视频工具 一款为自媒体创作者设计的 全自动视频生成工具,输入文本即可输出高质量视频,大幅提升内容创作效率。视频演示:https://leeseean.github.io/Text2Video/?t23 ✨ 功能亮点 功能模块说明📝 智能分…...
Python生活手册-NumPy数组创建:从快递分拣到智能家居的数据容器
一、快递分拣系统(列表/元组转换) 1. 快递单号录入(np.array()) import numpy as np快递单号入库系统 快递单列表 ["SF123", "JD456", "EMS789"] 快递数组 np.array(快递单列表) print(f"…...
Cmake编译wxWidgets3.2.8
一、下载库源代码 去wxWidgets - Browse /v3.2.8 at SourceForge.net下载wxWidgets-3.2.8.7z 二、建立目录结构 1、在d:\codeblocks目录里新建wxWidgets_Src目录 2、把文件解压到该目录 3、建立 CB目录,并在该目录下分别建立 Debug 和 Release目录 三、使用Cmake…...
2.在Openharmony写hello world
原文链接:https://kashima19960.github.io/2025/03/21/openharmony/2.在Openharmony写hello%20world/ 前言 Openharmony 的第一个官方例程的是教你在Hi3861上编写hello world程序,这个例程相当简单编写 Hello World”程序,而且步骤也很省略&…...
「OC」源码学习——对象的底层探索
「OC」源码学习——对象的底层探索 前言 上次我们说到了源码里面的调用顺序,现在我们继续了解我们上一篇文章没有讲完的关于对象的内容函数,完整了解对象的产生对于isa赋值以及内存申请的内容 函数内容 先把_objc_rootAllocWithZone函数的内容先贴上…...
从0开始学习大模型--Day01--大模型是什么
初识大模型 在平时遇到问题时,我们总是习惯性地去运用各种搜索引擎如百度、知乎、CSDN等平台去搜索答案,但由于搜索到的内容质量参差不齐,检索到的内容只是单纯地根据关键字给出内容,往往看了几个网页都找不到答案;而…...