C++类与对象

class

class基本语法

class ClassName {
public:
// 公有成员
Type memberVariable; // 数据成员
ReturnType memberFunction(); // 成员函数声明 private:
// 私有成员
Type privateMemberVariable; // 数据成员
ReturnType privateMemberFunction(); // 成员函数声明 protected:
// 保护成员
Type protectedMemberVariable; // 数据成员
ReturnType protectedMemberFunction(); // 成员函数声明
};

Important points

  • public :公有访问权限,类的外部可以访问

  • private:私有访问权限,只有类的内部可以访问。

  • protected:保护访问权限,只有类的内部和派生类可以访问。

  • 注意,默认权限为private

这里可以实现成员变量的被操作权限

在class中,声明数组大小时,如果声明大小使用的变量为class内的变量时,应当如下

class Map{
public:
const static int maxn =4343;
int next[maxn]={};
};

或者建议使用 array 或者 vector

关于class中的static修饰词警示后人

在class中访问没有static修饰的函数与变量都是需要一个已经创建的对象才可以访问。

但是有了static修饰以后便会有所不同。有static修饰的变量和函数仅仅属于这个类本身,不属于某个特定的对象,但是其仍然拥有访问权限的设置!!

其可以直接被如下方式访问

class classname{
public:
static functionname(){/*content*/}
static cnt;
}; int main (){
classname::functionname();
cout<<classname::cnt<<endl;
}

构造函数与析构函数

构造函数语法:类名(){}

  1. 构造函数,没有返回值也不写void
  2. 函数名称与类名相同
  3. 构造函数可以有参数,因此可以发生重载
  4. 程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次

析构函数语法: ~类名(){}

  1. 析构函数,没有返回值也不写void
  2. 函数名称与类名相同,在名称前加上符号 ~
  3. 析构函数不可以有参数,因此不可以发生重载
  4. 程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次

注: 这两个函数会被设置访问权限,可以限制类的创建和销毁!!

构造函数分类与调用

两种分类方式:

​ 按参数分为: 有参构造和无参构造

​ 按类型分为: 普通构造和拷贝构造

三种调用方式:

​ 括号法 ``````

​ 显示法

​ 隐式转换法

深拷贝与浅拷贝的差别:

浅拷贝(Shallow Copy)

浅拷贝是指复制对象时,新的对象和原始对象共享相同的内存地址。换句话说,浅拷贝仅复制对象的值(即指针和基本数据类型的值),而不是指针所指向的实际对象。

特点:

  1. 共享引用: 如果对象包含指针或引用,浅拷贝只复制指针的值,因此原始对象和拷贝对象的指针会指向同一块内存区域。
  2. 性能: 浅拷贝比深拷贝通常更快,因为它只需要复制指针和基本数据类型的值,而不需要递归地复制所有引用的对象。
  3. 潜在问题: 由于原始对象和拷贝对象共享相同的内存区域,当一个对象修改了指针指向的内容时,另一个对象的内容也会受到影响。此共享可能导致悬挂指针(如果一个对象释放了共享内存,另一个对象会变成悬挂状态)或数据不一致的问题。

深拷贝(Deep Copy)

深拷贝则是创建一个新对象,并递归地复制原始对象所引用的所有对象。换句话说,深拷贝不仅复制对象的值,还复制对象内包含的所有指针指向的对象,从而创建一个完全独立的新对象。

特点:

  1. 独立性: 原始对象和深拷贝对象之间没有共享的内存区域,修改一个对象不会影响另一个对象。
  2. 性能: 深拷贝可能较慢,因为它涉及递归地复制所有指针所指向的内容。
  3. 内存管理: 深拷贝通常需要编写额外的代码来确保正确管理内存,例如在析构函数中释放分配的内存,避免内存泄漏。

构造函数的初始化列表

class Person {
public: ////传统方式初始化
//Person(int a, int b, int c) {
// m_A = a;
// m_B = b;
// m_C = c;
//} //初始化列表方式初始化
Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c) {}
void PrintPerson() {
cout << "mA:" << m_A << endl;
cout << "mB:" << m_B << endl;
cout << "mC:" << m_C << endl;
}
private:
int m_A;
int m_B;
int m_C;
};

类对象作为类成员的构造和析构函数调用顺序

C++类中的成员可以是另一个类的对象,我们称该成员为 对象成员

//构造的顺序是 :先调用对象成员的构造,再调用本类构造
//析构顺序与构造相反

静态成员

静态成员变量

  • 所有对象共享同一份数据

  • 在编译阶段分配内存

  • 类内声明,类外初始化(一定要记着初始化,不然编译错误不显示!!!)

    class Example {
    public:
    static int staticVar; // 声明静态成员变量
    }; int Example::staticVar = 0; // 定义并初始化静态成员变量

静态成员函数(static)

  • 所有对象共享同一个函数
  • 静态成员函数只能访问静态成员变量(其实只需要在参数上加入一个对象就可以访问对象的成员变量)

静态函数可以在类里面声明,在类外定义!!

常成员(const)

const 修饰成员函数

  • 保证不会改变对象的状态,但是可以调用更改 static 修饰的变量

  • 只可以调用其他const成员函数

    为了保证在const成员函数中,不会对对象进行改变

    可以调用静态函数!!!

  • 可以返回一个值,但是如果返回的是指针or引用,则必须加上const

    class Type{
    int a;
    const int* GO() const{//int const* GO() const 这样也可以
    return &a;
    }
    };

    这一条并不适用于 static变量: 当返回的值为static变量的地址或引用时,可以不用static

    注意:在这里在再次区分一下 const int * int const * int * const

    前两者是一样的,定义的指针不可以修改对应的地址

    第三者是指该指针所指的地址不可修改,但是可以通过指针修改内容

  • 成员变量加上 \(mutable\) 就可以不受以上规则限制,而可被const函数修改和返回非常量指针

总结: 常函数保证了不会通过其对对象有任何形式的修改包括指针与引用,但是对应于 \(static,mutabl\) 修饰的变量例外

const关键字的使用方式:

const int* () const{}

前一个 \(const\) 用于修饰返回值,后一个用于修饰函数为静态函数

注意:函数可以反回 \(const\) 的值,但是没有意义,因为其返回的值是拷贝。但是返回 \(const\) 的指针与引用是有意义的。

const MyClass& getObject() const {
static MyClass obj;
return obj;
}
OR
const MyClass* getObject() const {
static MyClass obj;
return obj;
}

常对象

  • 声明对象前加const称该对象为常对象
  • 常对象只能调用常函数
  • 常对象可以修改静态变量,调用静态函数,修改 \(mutable\) 变量

友元

通过声明友元的方式,可以使C++中某个类的private和protected的变量和函数被其他类和函数访问

友元类

友元类函数

友元全局函数

class People{
friend class Dorm; //友元类
friend void get_password(const People&,const Dorm&); //友元函数
public:
const int ID;
void Change_drompassword(const int&,const int&,const int &,Dorm&);
public:
People(int id,int Password): ID(id),password(Password){
cout<<"creat a new person\n";
}
private:
int password;
}; class Dorm{
friend class People;
friend void get_password(const People & a,const Dorm & b);
friend void People::Change_drompassword(const int&,const int&,const int &,Dorm&); //友元类函数
private:
int get_number(){
return dorm_number;
}
int dorm_number;
int dorm_password;
public:
Dorm(int number,int password):dorm_number(number),dorm_password(password){
cout<<"creat a drom!\n";
}
};

Attention:

  • 在声明友元类函数之前,一定要保证该类已经被声明完成(提前声明不可以,因为complier只是知道了有这个类而不知道这个类的具体内容)。例如:将以上代码的两个类的定义交换位置为导致 $ incompleting $ 错误
  • 在声明有友元函数时,参数列表不用写参数名称,但是 \(const~,\&~\) 不可拉下

友元的注意事项

  1. 不具有继承关系:友元关系不会被继承。例如,如果类B是类A的友元,类C继承了类A,类C不会自动成为类B的友元。
  2. 友元不具有传递性:如果类A是类B的友元,类B不是自动成为类A的友元。
  3. 友元关系是单向的:即使类A是类B的友元,类B并不能自动访问类A的私有成员,除非类B也显式地声明类A为友元。

\(C++\) 中的输入输出流

输入流

  • 用于从外部源(如键盘或文件)读取数据。

  • 主要的输入流对象是std::cin,它表示标准输入流。

  • cin.fail() 用于检查输入是否成功

  • cin.ignore() 函数

    • 忽略指定数量的字符

      std::cin.ignore(count);//count 代表数量
    • 忽略直到特定字符或 EOF:

      std::cin.ignore(count, delimiter);//delimiter 代表分隔符,这个分隔符也会被舍去
      std::cin.ignore(numeric_limits<std::streamsize>::max(), '\n')://忽略输入流中的特定字符或直到遇到换行符。

输出流

  • 用于将数据输出到外部目标(如显示器或文件)。
  • 主要的输出流对象是std::cout,它表示标准输出流。
  • cout.flush() 刷新输出流,确保所有缓冲区的数据被输出到终端。

错误流

  • 用于输出错误信息。

  • 主要的错误流对象是std::cerr,它用于打印错误信息。

日志流(Log Stream)

  • 用于输出警告或日志信息。
  • 主要的日志流对象是std::clog

注: 以上四个标准流的使用方法都是一样的

int x;
std::cin >> x;
std::cout << "Hello, World!" << std::endl;
std::cerr << "An error occurred!" << std::endl;
std::clog << "This is a log message." << std::endl;

文件流

除了标准流,C++还支持文件流,用于从文件中读取数据或将数据写入文件。文件流的主要类有:

  • std::ifstream:用于输入文件流。
  • std::ofstream:用于输出文件流。
  • std::fstream:用于读写文件流(即同时支持输入和输出)。
#include <iostream>
#include <fstream> // 引入文件流 int main() {
// 写入文件
std::ofstream outFile("example.txt");
if (outFile.is_open()) {
outFile << "Hello, File!" << std::endl;
outFile.close();
} // 读取文件
std::ifstream inFile("example.txt");
std::string line;
if (inFile.is_open()) {
while (getline(inFile, line)) {
std::cout << line << std::endl;
}
inFile.close();
} return 0;
}
文件打开模式

首先在打开文件流是可以设置打开模式的,设置方法如下

std::fstream file("example.txt", std::ios::in | std::ios::out | std::ios::ate);

注: 当要使用多个打开模式时,可以用 | 将其链接

接下来介绍文件打开模式

  • std::ios::in:用于读操作。

  • std::ios::out:用于写操作,文件内容会被覆盖(如果文件存在)。

  • std::ios::app:用于追加操作,所有写入的数据会追加到文件末尾。

  • std::ios::ate:文件打开时将文件指针定位到文件末尾,适用于需要在文件末尾开始读写的情况。

  • std::ios::trunc:如果文件已经存在,会清空文件内容,通常与 std::ios::out 一起使用。

  • std::ios::binary 以二进制的方式打开文件,不会进行仍何文本转化(比如换行符转化)

    #include <iostream>
    #include <fstream>
    #include <vector> int main() {
    // 文件名
    const char* filename = "example.bin"; // 打开文件以二进制模式
    std::ifstream file(filename, std::ios::binary); // 检查文件是否成功打开
    if (!file) {
    std::cerr << "无法打开文件: " << filename << std::endl;
    return 1;
    } // 移动文件指针到文件末尾以获取文件大小
    file.seekg(0, std::ios::end);
    std::streamsize size = file.tellg();
    file.seekg(0, std::ios::beg); // 使用 std::vector 存储文件内容
    std::vector<char> buffer(size); // 读取文件内容到 buffer 中
    if (file.read(buffer.data(), size)) {
    // 处理文件内容(示例中仅输出文件大小)
    std::cout << "文件大小: " << size << " 字节" << std::endl;
    // 这里可以根据需要处理 buffer 中的数据
    } else {
    std::cerr << "读取文件失败" << std::endl;
    } // 关闭文件
    file.close(); return 0;
    }
    /*
    文件名:你需要指定你想要读取的文件名。示例中使用的是 "example.bin"。 打开文件:std::ifstream file(filename, std::ios::binary); 这行代码打开了指定的文件,并以二进制模式进行读取。 获取文件大小:使用 seekg 和 tellg 方法来确定文件的大小。 读取内容:file.read(buffer.data(), size); 这行代码将文件内容读取到 buffer 中。 错误检查:在打开文件和读取文件后,检查是否成功执行这些操作。 关闭文件:使用 file.close(); 关闭文件。
    */

以上打开方式在 ifstream ofstream 中使用是没有问题的,只不过要注意不要把输出的文件打开方式安在输入文件流上面了,会导致文件流无法正常打开的问题

最后让我们来介绍一下在 fstream 中使用这些文件打开方式会出现的一些问题

  • 单独使用 app,ate,trunc 都是不行的,因为他们没有给出文件的读写模式,所以要加上 in out

  • 有个作死的玩法

    fstream IN(".in", std::ios::out);
    cout<<IN.is_open()<<endl;
    int a;
    IN>>a;
    IN<<1111<<endl;

    然后你就会发现输出了个寂寞

定位输出指针
std::ios::beg //开头指针
std::ios::cur //当前指针
std::ios::end //文件末尾

搭配函数 seekg() 使用

    // 将读指针移动到文件开头
inFile.seekg(0, std::ios::beg);
// 将读指针移动到当前指针位置向后偏移5个字符的位置
inFile.seekg(5, std::ios::cur);

\(istream\) 与 \(ostream\)

这两是流的两种类型,是最基础的,一个是输入流,一个是输出流

重载运算符的时候就是用的这两

//笔者摆烂了,BF5见!

运算符重载

重载函数的两种形式

重载函数和其他函数一样都会存在访问权限问题!!!

友函数重载
class Grade{
friend ostream& operator<<(ostream& out,const Grade & P);
private:
int grade_Chnese,grade_program,grade_math;
Grade(int a,int b,int c,bool OP):grade_Chnese(a),grade_program(b),grade_math(c){
if(OP) cout<<"insert grade succesfully!\n";
}
Grade(){}
}; ostream& operator <<(ostream & OUTT,const Cnt & b){
OUTT<<b.cnt<<endl;
return OUTT;
}

注: 在友函数重载中,两个参数分别代表左右操作符(其实也可以不用加 friend 如果不用访问 privateprotected 的话)

成员函数重载
class Grade{
public:
Grade operator + (const Grade& A) const{
return Grade(A.grade_Chnese+grade_Chnese,A.grade_program+grade_program,A.grade_math+grade_math,0);
}
}

注: 在成员函数重载中对象本身会作为左操作数,参数作为右操作数

运算符重载实例

注: + - * / > < >= <= == 都比较简单,参考结构体重构一样的

注: 建议在定义参数时使用常变量+引用,防止意外的更改以及加快速度

左移右移符号(输入输出流操作符)

由于在左移右移符号中,对象始终处于右操作数,所以只可以使用友函数的方法

class Grade{
friend ostream& operator<<(ostream& out,const Grade & P);
friend class People;
private:
int grade_Chnese,grade_program,grade_math;
Grade(int a,int b,int c,bool OP):grade_Chnese(a),grade_program(b),grade_math(c){
if(OP) cout<<"insert grade succesfully!\n";
}
Grade(){}
public:
Grade operator + (const Grade& A) const{
return Grade(A.grade_Chnese+this->grade_Chnese,A.grade_program+this->grade_program,A.grade_math+this->grade_math,0);
}
}; ostream& operator<<(ostream& Gut,const Grade & P){
Gut<<P.grade_Chnese<<" "<<P.grade_program<<" "<<P.grade_math<<endl;
return Gut;
}
自增自减符号
class Cnt{
public:
double cnt;
Cnt(long double a=0){cnt=a;}
Cnt& operator ++(){
(this->cnt)+=1;
return *this;
}//先修改,后返回引用
Cnt operator ++(int){//这个int用于占位,是C++编译器用于区分这两个重载的标志,无实际意义!!
Cnt a=*this;
cnt+=1;
return a;
}//先返回值,后修改
};

继承

继承的基本概念:

  1. 基类(Base Class):被继承的类,提供共有的属性和方法。
  2. 派生类(Derived Class):从基类继承的类,可以重用基类的成员,并且可以扩展或修改这些成员。

继承的类型

  1. 公有继承(Public Inheritance)

    • 最常用的继承方式,表示派生类“是一个”基类的特殊类型。
    • 基类的公有成员在派生类中保持公有,基类的保护成员在派生类中保持保护。
  • 基类的私有成员不能直接访问。

    class Base {
    public:
    int pubValue;
    protected:
    int protValue;
    private:
    int privValue;

};

class Derived : public Base {

public:

void accessMembers() {

pubValue = 1; // 可以访问公有成员

protValue = 2; // 可以访问保护成员

// privValue = 3; // 不能访问私有成员

}

};

2. **保护继承(Protected Inheritance)**:

    - 基类的公有和保护成员在派生类中都变成保护成员。
- 不允许外部代码通过派生类访问这些成员,但派生类内部可以访问。 ```cpp
class Derived : protected Base {
public:
void accessMembers() {
pubValue = 1; // 可以访问公有成员(现在是保护成员)
protValue = 2; // 可以访问保护成员
// privValue = 3; // 不能访问私有成员
}
};
``` 3. **私有继承(Private Inheritance)**:
- 基类的公有和保护成员在派生类中都变成私有成员。
- 外部代码不能通过派生类访问这些成员,但派生类内部可以访问。 ```cpp
class Derived : private Base {
public:
void accessMembers() {
pubValue = 1; // 可以访问公有成员(现在是私有成员)
protValue = 2; // 可以访问保护成员
// privValue = 3; // 不能访问私有成员
}
};

注意: 虽然说基类 private 的成员是无法在派生类中被调用的,但是实际上他是被继承过来了的,只是被编译器隐藏了。

继承的特点

  1. 构造函数和析构函数

    • 派生类的构造函数会调用基类的构造函数。基类的构造函数先执行,派生类的构造函数后执行。
    • 派生类的析构函数会调用基类的析构函数。派生类的析构函数先执行,基类的析构函数后执行。
class Base {
public:
Base() { std::cout << "Base Constructor\n"; }
virtual ~Base() { std::cout << "Base Destructor\n"; }
}; class Derived : public Base {
public:
Derived() { std::cout << "Derived Constructor\n"; }
~Derived() { std::cout << "Derived Destructor\n"; }
};

如果你想向基类的构造函数中输入参数,可以用以下方式: ```C++
class People{
public:
string Name;
People(){cout<<"creat a people\n";}
People(const string& name,const string& id,const string& phone_num):Name(name),ID(id),Phone_num(phone_num){cout<<"creat a new people\n";}
protected:
string ID;
string Phone_num;
}; class Student: public People{
public:
Student(){cout<<"creat a new student\n";}
Student(const string& name,const string& id,const string& phone_num):
People(name,id,phone_num){//在这里,使用参数列表的方式注入参数
cout<<"creat a new student\n";
}
};

这样写是不对的:

class People{
public:
string Name;
People(){cout<<"creat a people\n";}
People(const string& name,const string& id,const string& phone_num):Name(name),ID(id),Phone_num(phone_num){cout<<"creat a new people\n";}
protected:
string ID;
string Phone_num;
}; class Student: public People{
public:
Student(){cout<<"creat a new student\n";}
Student(const string& name,const string& id,const string& phone_num):
People::Name(name),People::ID(id),People::Phone_num(phone_num){
cout<<"creat a new student\n";
}
};
  1. 变量名冲突:

    多继承中如果父类中出现了同名情况,子类使用时候要加作用域

    class People{
    public:
    string Name;
    People(){cout<<"creat a people\n";}
    People(const string& name,const string& id,const string& phone_num):Name(name),ID(id),Phone_num(phone_num){cout<<"creat a new people\n";}
    void Print();
    protected:
    string ID;
    string Phone_num;
    }; class Student: public People{
    public:
    string ID;
    Student(){cout<<"creat a new student\n";}
    Student(const string& name,const string& id,const string& phone_num,const string & IDD):People(name,id,phone_num),ID(IDD){
    cout<<"creat a new student\n";
    }
    void OKK(){
    cout<<People::ID<<" "<<ID<<endl;//这里,加入作用域就ok啦
    }
    };
  2. 虚继承

    • 用于解决菱形继承(钻石继承)问题,确保基类只被初始化一次。
    • 通过在基类前加上 virtual 关键字来声明虚继承。
    class Base {
    public:
    int value;
    }; class Derived1 : virtual public Base {};
    class Derived2 : virtual public Base {}; class Final : public Derived1, public Derived2 {};//在Final 类中就只会有一个 Base::value 避免了冗余和二义性
  3. 多重继承

    • C++支持一个类从多个基类继承。这种方式允许一个类同时继承多个类的功能,但需要小心避免命名冲突和不一致的问题。
    class A {
    public:
    void funcA() {}
    }; class B {
    public:
    void funcB() {}
    }; class C : public A, public B {
    public:
    void funcC() {}
    };

使用继承的注意事项

  • 继承的正确性:确保使用继承关系能够表达类之间的实际关系,避免使用继承来简单地复用代码。
  • 封装性:使用保护或私有继承可以减少对基类实现细节的依赖。
  • 多态性:利用虚函数(virtual functions)和动态绑定(dynamic binding)来实现运行时多态。

继承是C++的一个强大特性,但合理地使用它对于维护代码的可读性和可维护性是非常重要的。

多态

C++中的多态主要有两种类型:

  1. 编译时多态(静态多态)
  2. 运行时多态(动态多态)

编译时多态(静态多态)

编译时多态发生在编译阶段,主要通过函数重载(Function Overloading)和运算符重载(Operator Overloading)来实现。

运行时多态(动态多态)

虚函数:在基类中声明为virtual的成员函数,允许派生类重写,并在运行时通过基类指针或引用调用派生类的实现。

class Base {
public:
virtual void show() const {
std::cout << "Base class show function" << std::endl;
} virtual ~Base() {} // 虚析构函数,确保正确释放派生类资源
}; class Derived : public Base {
public:
void show() const override { // 重写基类的 show 函数
std::cout << "Derived class show function" << std::endl;
}
};

这里 override 表示这是一个重写的函数,如果是 override final 指明派生类中某个虚函数不仅是重写了基类的虚函数,而且不允许进一步重写

在基类中也可以采用纯虚函数的写法

纯虚函数语法:virtual 返回值类型 函数名 (参数列表)= 0 ;

当类中有了纯虚函数,这个类也称为抽象类

抽象类特点

  • 无法实例化对象(就是无法声明出对象)
  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类

\(Attention:\)

当派生类的成员占据了堆的空间时(就是派生类是被 new 函数弄个出来的时候),基类的析构函数必须虚函数(纯虚函数也OK),不然会导致在 delete 派生对象时,只会调用基类的析构函数,而不会调用派生类的析构函数,导致出现内存泄漏。

#include <iostream>
//Wrong
class Base {
public:
Base() { std::cout << "Base constructor\n"; }
~Base() { std::cout << "Base destructor\n"; } // 非虚析构函数
}; class Derived : public Base {
public:
Derived() { std::cout << "Derived constructor\n"; }
~Derived() { std::cout << "Derived destructor\n"; }
}; int main() {
Base* basePtr = new Derived();
delete basePtr; // 只调用 Base 的析构函数
return 0;
}
#include <iostream>
//corect
class Base {
public:
Base() { std::cout << "Base constructor\n"; }
virtual ~Base() { std::cout << "Base destructor\n"; } // 虚析构函数
}; class Derived : public Base {
public:
Derived() { std::cout << "Derived constructor\n"; }
~Derived() { std::cout << "Derived destructor\n"; }
}; int main() {
Base* basePtr = new Derived();
delete basePtr; // 现在会调用 Derived 的析构函数,然后调用 Base 的析构函数
return 0;
}

撒花完结!!!

初学者浅析C++类与对象的更多相关文章

  1. C#核心基础--浅谈类和对象的概念

    浅谈类和对象的概念 一.什么是类?什么是对象? 学习一门面向对象编程语言,我们必须得知道什么是类?什么是对象? 类(Class)实际上是对某种类型的对象定义变量和方法的原型.它表示对现实生活中一类具有 ...

  2. C++ 关于类与对象在虚函数表上唯一性问题 浅析

    [摘要] 非常多教材上都有介绍到虚指针.虚函数与虚函数表.有的说类对象共享一个虚函数表,有的说,一个类对象拥有一个虚函数表.还有的说,不管用户声明了多少个类对象,可是,这个VTABLE虚函数表仅仅有一 ...

  3. JavaScript 浅析数组对象与类数组对象

    数组(Array对象) 数组的操作 创建数组方法 添加与修改数组元素 删除数组元素 使用数组元素 遍历数组元素 多维数组 数组相关的函数 concat() join() pop() push() sh ...

  4. 初识python中的类与对象

    这篇博客的路线是由深入浅,所以尽管图画的花花绿绿的很好看,但是请先关注我的文字,因为初接触类的小伙伴直接看类的实现可能会觉得难度大,只要耐着性子看下去,就会有一种“拨开迷雾看未来”的感觉了. 一.py ...

  5. Python 面向对象(创建类和对象,面向对象的三大特性是指:封装、继承和多态,多态性)

    概念:                                                                                                 ...

  6. 孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习

     孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.close() 当一个file对象执行此方法时,将关闭当前 ...

  7. C#类,对象,类成员简介

    本节内容 1.类(class)是现实世界事物的模型 2.类与对象的关系,什么时候叫“对象”什么时候叫“实例” 3.引用变量与实例的关系 4.类的三大成员: ①属性(Property): ②方法(Met ...

  8. C++类和对象到底是什么意思?

    C++ 是一门面向对象的编程语言,理解 C++,首先要理解类(Class)和对象(Object)这两个概念. C++ 中的类(Class)可以看做C语言中结构体(Struct)的升级版.结构体是一种构 ...

  9. 类和对象在JVM中是如何存储的,竟然有一半人回答不上来!

    前言 这篇博客主要来说说类与对象在JVM中是如何存储的,由于JVM是个非常庞大的课题,所以我会把他分成很多章节来细细阐述,具体的数量还没有决定,当然这不重要,重点在于是否可以在文章中学到东西,是否对J ...

  10. 如何讲清楚 Java 面向对象的问题与知识?(类与对象,封装,继承,多态,接口,内部类...)

    写在最前面 这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解.所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项 ...

随机推荐

  1. BST二叉查找树的接口设计

    /*************************************************************************************************** ...

  2. 【CMake系列】02-第一个CMake项目

    本节我们用CMake 构建我们的第一个helloword的项目,从更细的粒度上了解CMake在做什么,对编写CMakeLists.txt 进入初步引入 本专栏的实践代码全部放在 github 上,欢迎 ...

  3. Docker 容器中镜像导出/导入

    目录 [容器]镜像导出/导入 导出 导入 带标签 不带标签,后期修改 [仓库]镜像导出/导入 导出 导入 导入(完整命令) 创建一个简单的Docker镜像 利用docker ps -a命令查看要导出的 ...

  4. 玄机蓝队靶场_应急响应_02:apache日志分析

    日志分析这块,感觉都是对grep.awk.sort.wc.uniq,这几个命令的使用. 一:靶场 (1)直接cd到linux日志, cd /var/log 发现apache2目录, cd ./apac ...

  5. Unable to tunnel through proxy. Proxy returns "HTTP/1.1 503 Service Unavailable"

    背景: 某日,一正常项目迁移到新的服务器 新的服务器,需要使用代理来访问之前能直接访问的接口,加完代理之后,发现无法获取数据了 报错: org.springframework.web.client.R ...

  6. VC 单文档FormView视图增加打印预览

    1修改my.rc文件二处 3 TEXTINCLUDE BEGIN "#define _AFX_NO_OLE_RESOURCES\r\n" "#define _AFX_NO ...

  7. JAVA与.NET DES加密解密

    项目需要在两个系统间采用DES加密,一个系统为JAVA开发的,另外一个.Net开发的 在网上找了很多写法但加密出的数据两个系统都无法匹配, 在做了小修改以后终于可以用了,已经测试过 JAVA版本 im ...

  8. 【学习笔记】状压DP

    状态压缩DP 对于一个集合,他一有\(2^n\)个子集,而状态压缩就是枚举这些子集,每一个状态就是一个由\(01\)构成的集合,如果为\(0\)就表示不选当前的元素,否则就表示选.因为状态压缩将每一个 ...

  9. HarmonyOS ArkTS基础语法

    前提:安装开发工具       教程:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tools_overview-0 ...

  10. 【赵渝强老师】在MongoDB中使用游标

    一.什么是游标? 游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行前进或向后浏览数据的能力. 游标实际上是一种能从包括多条数据记录的结果集 ...