C++朝花夕拾

目录

目录

函数分文件编写

野指针

const与指针 

const修饰指针——常量指针

const修饰常量——指针常量

const既修饰指针,又修饰常量

const阻止函数修改

delete和delete[]的区别

内存四区(面试会问?)

程序运行前

代码区

全局区

程序运行后 

栈区

堆区

new、delete——开辟、释放堆区内存

引用

常量引用

封装

访问权限

class和struct的区别

拷贝构造函数

调用时机

构造函数调用规则

深拷贝和浅拷贝(面试经典问题)

错误场景

解决

简化构造函数——初始化列表

语法

类中嵌套类对象

静态成员——前加static关键字

成员变量和成员函数分开存储

const修饰成员函数

友元

全局函数做友元

类做友元

成员函数做友元

运算符重载(非常重要)

加号运算符重载

左移运算符重载

递增运算符重载(int占位参数的作用)

赋值运算符重载(注意深浅拷贝的问题)

函数调用运算符重载和匿名函数对象

匿名函数对象

继承

继承方式

从父类继承过来的成员,哪些属于子类对象中?

父类和子类的构造和析构顺序是谁先谁后?

菱形继承(面试会考?)

虚继承——解决菱形问题

底层原理

多态(面试会问?)

原理剖析(重要)  

空类和不带虚函数的空类sizeof值为1,为什么?

带虚函数的空类sizeof值为多少?为什么?​编辑

虚函数实现多态原理剖析(重要)

纯虚函数和抽象类

概念

虚析构和纯虚析构

使用场景

解决

C++文件操作

职工管理系统

gitee项目地址

遇到的问题

1.抽象类(含有纯虚函数)无法实例化,如何创建数组来存放该抽象类的子类对象?

2.注意命名空间问题,有的结构漏掉命名空间可能会报语法错误(太恶心了!!!)

3.使用stringsteam拼接字符串

4.从文件中读取数据,这块真的恶心我半天,wcnm!!!

lambda表达式



函数分文件编写

作用:让代码结构更加清晰

 example:

野指针

 

const与指针 

 const修饰指针有三种情况:

1.const修饰指针——常量指针

2.const修饰常量——指针常量

3.const既修饰指针,又修饰常量

const修饰指针——常量指针

example:

int a=10;
int b=10;
const int *p = &a;

在指针前面加上const限定

特点:

指针的指向可以修改,但是指针指向的值不可以修改。

可以修改指针的指向

 不可以修改指针指向的值

const修饰常量——指针常量

example:

int a = 10;
int b = 10;
int * const p = &a;

在变量之前加上const限定

特点:

指针的指向不可以修改,指向的值可以修改

const既修饰指针,又修饰常量

example:

int a = 10;
int b = 10;
const int* const p = &a;

在指针和变量的前面都加const限定

特点:

指针的指向不可以修改,指针的值也不能修改

const修饰*,*p不能修改——常量指针

const修饰p,p不能修改(指向的位置不可以修改)——指针常量

const阻止函数修改

传进来的参数前加const可以防止参数被修改(在传送为指针或者引用的情况下)

delete和delete[]的区别

只要记住new和delete一起用,new[]和delete[]一起用就行了

内存四区(面试会问?)

  

程序运行前

程序编译后,生成exe可执行程序,未执行exe前分为两个区域:代码区、全局区

代码区

特点:存放CPU机器指令、共享、只读

共享:exe可能会频繁执行,在内存中有一份代码即可

只读:防止指令被意外修改

全局区

存放全局变量、静态变量(static修饰)、常量(字符串常量)

特点:全局区的数据在程序结束后由操作系统释放

const修饰的局部变量不在全局区中

程序运行后 

栈区

注意

不要返回局部变量的地址,栈区开辟的数据由编译器自动释放。

堆区

new、delete——开辟、释放堆区内存

引用

本质:引用的本质在C++内部实现是一个指针常量(不可以修改指针的指向,但可以修改指向的值)

常量引用

使用场景:用来修饰形参,防止误操作 

ex:

const防止val被修改 

封装

访问权限

有三种:

public(公共):成员类内可以访问,类外也可以访问

protected(保护):类内可以访问,类外不可以访问  儿子也可以访问父亲中的保护内容

private(私有):类内可以访问,类外不可以访问 儿子不能访问父亲中的私有内容

class和struct的区别

拷贝构造函数

调用时机

C++中拷贝构造函数调用时机通常有三种情况

  • 使用一个已经创建完毕的对象来初始化一个新对象(主动调用)

  • 值传递的方式给函数参数传值

  • 以值方式返回局部对象

第三点注意!有的编译器会进行优化,此时可能不会调用拷贝构造函数(我用的VS2022是会这样的)

ex:

class Person {
public:Person() {cout << "无参构造函数!" << endl;mAge = 0;}Person(int age) {cout << "有参构造函数!" << endl;mAge = age;}Person(const Person& p) {cout << "拷贝构造函数!" << endl;mAge = p.mAge;}//析构函数在释放内存之前调用~Person() {cout << "析构函数!" << endl;}
public:int mAge;
};//1. 使用一个已经创建完毕的对象来初始化一个新对象
void test01() {Person man(100); //p对象已经创建完毕Person newman(man); //调用拷贝构造函数Person newman2 = man; //拷贝构造//Person newman3;//newman3 = man; //不是调用拷贝构造函数,赋值操作
}//2. 值传递的方式给函数参数传值
//相当于Person p1 = p;
void doWork(Person p1) {}
void test02() {Person p; //无参构造函数doWork(p);
}//3. 以值方式返回局部对象
Person doWork2()
{Person p1;cout << (int *)&p1 << endl;return p1;
}void test03()
{Person p = doWork2();cout << (int *)&p << endl;
}int main() {//test01();//test02();test03();system("pause");return 0;
}

构造函数调用规则

默认情况下,c++编译器至少给一个类添加3个函数

1.默认构造函数(无参,函数体为空)

2.默认析构函数(无参,函数体为空)

3.默认拷贝构造函数,对属性进行值拷贝

构造函数调用规则如下:

  • 如果用户定义有参构造函数,c++不在提供默认无参构造,但是会提供默认拷贝构造

  • 如果用户定义拷贝构造函数,c++不会再提供其他构造函数

深拷贝和浅拷贝(面试经典问题)

浅拷贝:简单的赋值拷贝操作

深拷贝:在堆区重新申请空间,进行拷贝操作   

错误场景

#include<iostream>
using namespace std;class Person
{
public:Person(int age, int height){this->age = age;this->height = new int(height);}~Person(){if (this->height != NULL){delete this->height;this->height = NULL;}}private:int age;int* height;
};int main()
{Person p1(18,160);Person p2 = p1;return 0;
}

运行程序产生报错,原因:

程序在结束时会自动执行析构函数,先释放p2再释放p1(栈中先进后出) 

会对0x0011这块地址调用两次delete导致程序出错



解决

自己写一个拷贝构造函数,进行深拷贝

简化构造函数——初始化列表

语法

构造函数():属性1(值1),属性2(值2)... {}

example:

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;
};int main() {Person p(1, 2, 3);p.PrintPerson();system("pause");return 0;
}

类中嵌套类对象

class A {}
class B
{A a;
}

创建并由系统销毁一个B对象,则:

1.调用A对象的构造函数

2.调用B对象的构造函数

3.调用B对象的析构函数

4.调用A对象的析构函数

静态成员——前加static关键字

  • 静态成员变量

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

    • 在编译阶段分配内存

    • 类内声明,类外初始化

  • 静态成员函数

    • 所有对象共享同一个函数

    • 静态成员函数只能访问静态成员变量

成员变量和成员函数分开存储

class Person {
public:Person() {mA = 0;}//非静态成员变量占对象空间int mA;//静态成员变量不占对象空间static int mB; //函数也不占对象空间,所有函数共享一个函数实例void func() {cout << "mA:" << this->mA << endl;}//静态成员函数也不占对象空间static void sfunc() {}
};int main() {cout << sizeof(Person) << endl;system("pause");return 0;
}

const修饰成员函数

常函数:

  • 成员函数后加const后我们称为这个函数为常函数

  • 常函数内不可以修改成员属性

  • 成员属性声明时加关键字mutable后,在常函数中

    依然可以修改

常对象:

  • 声明对象前加const称该对象为常对象

  • 常对象只能调用常函数

代码示例

#include<iostream>
using namespace std;class Person
{
public:void myFunc1() const{//a = 10; 报错,常函数不能修改不带mutable的成员变量b = 10;}void myFunc2(){}
private:int a;mutable int b;};int main()
{const Person p;//声明常对象//p.myFunc2();报错,常对象只能调用常函数p.myFunc1()}

友元

目的:

让一个函数或者类 访问另一个类中私有成员

关键字:friend

实现方式:

  • 全局函数做友元

  • 类做友元

  • 成员函数做友元

全局函数做友元

在类中用friend关键字申明友元函数,在类外初始化。

代码示例:

#include<iostream>
using namespace std;class Building
{friend void goodGay(Building &b);
public:int livingRoom;
private:int bedRoom;
};void goodGay(Building& b)
{b.livingRoom = 1;cout << "我到客厅来了!" << endl;b.bedRoom = 1;cout << "我到卧室来了!" << endl;
}
int main()
{Building b; goodGay(b);return 0;
}

类做友元

在类中申明友元

friend class GoodGay;

代码示例

#include<iostream>
using namespace std;
class GoodGay;
class Building
{friend class GoodGay;
public:int livingRoom;
private:int bedRoom;};
class GoodGay
{
private:Building b;
public:void visit(){b.livingRoom = 1;cout << "我到客厅来了!" << endl;b.bedRoom = 1;cout << "我到卧室来了!" << endl;}
};
int main()
{GoodGay gg;gg.visit();return 0;
}

成员函数做友元

代码示例

#include<iostream>
#include<string>
using namespace std;class GoodGay
{
public:GoodGay();void visit1();//申请为友元成员函数void visit2();//不做处理
private:Building* b;
};class Building
{friend void GoodGay::visit1();
public:Building();string livingRoom;
private:string bedRoom;
};GoodGay::GoodGay()
{b = new Building;
}
Building::Building()
{livingRoom = "客厅";bedRoom = "卧室";
}
void GoodGay::visit1()//友元函数可以访问私有属性
{cout << "访问" << b->livingRoom << endl;cout << "访问" << b->bedRoom << endl;
}
void GoodGay::visit2()
{cout << b->livingRoom << endl;//cout << b.bedRoom << endl; 非友元函数无法访问私有属性}
int main()
{GoodGay gg;gg.visit1();return 0;
}

运算符重载(非常重要)

什么样的运算符可以用成员函数进行重载??

对象要在运算符的前面,如+、-、*

以加号为例,用成员函数重载+,则p3=p1+p2相当于p3=p1.operator+(p2)

成员函数重载运算符,则对象为运算符前的参数

又如:左移运算符无法使用成员函数运算符重载

cout<<p,运算符前的参数为cout而不为对象。

加号运算符重载

#include<iostream>
using namespace std;class Person
{
public:int m_A;int m_B;Person(){}Person(int a, int b){this->m_A = a;this->m_B = b;}//成员函数实现运算符重载//Person operator+(Person& p)//{//	Person tmp;//	tmp.m_A = this->m_A + p.m_A;//	tmp.m_B = this->m_B + p.m_B;//	return tmp;//}//};
//全局运算符重载
Person& operator+(Person& p1,Person& p2)
{Person tmp;tmp.m_A = p1.m_A + p2.m_A;tmp.m_B = p1.m_A + p2.m_B;return tmp;
}int main()
{Person p1(10,10);Person p2(5,15);Person p3 = p1 + p2;cout << p3.m_A << endl;cout << p3.m_B << endl;Person p4 = p1 + p2 + p3;return 0;
}

左移运算符重载

通常不会用成员函数重载左移运算符

#include<iostream>
#include<string>
using namespace std;class Person
{
private:string name;int age;
public:friend ostream& operator<<(ostream& cout, Person& p);Person(string name,int a){this->name = name;this->age = a;}int getAge(){return this->age;}string getName(){return this->name;}};ostream& operator<<(ostream& cout, Person& p)
{cout << "姓名:" << p.name << " 年龄:" << p.age;return cout;
}int main()
{ Person p("叶盛",25);cout << p << endl;return 0;
}

递增运算符重载(int占位参数的作用)

1.用int占位符来区分前置和后置递增

2.前置递增返回引用,后置递增返回值

class MyInteger {friend ostream& operator<<(ostream& out, MyInteger myint);public:MyInteger() {m_Num = 0;}//前置++MyInteger& operator++() {//先++m_Num++;//再返回return *this;}//后置++MyInteger operator++(int) {//先返回MyInteger temp = *this; //记录当前本身的值,然后让本身的值加1,但是返回的是以前的值,达到先返回后++;m_Num++;return temp;}private:int m_Num;
};ostream& operator<<(ostream& out, MyInteger myint) {out << myint.m_Num;return out;
}//前置++ 先++ 再返回
void test01() {MyInteger myInt;cout << ++myInt << endl;cout << myInt << endl;
}//后置++ 先返回 再++
void test02() {MyInteger myInt;cout << myInt++ << endl;cout << myInt << endl;
}int main() {test01();//test02();system("pause");return 0;
}

赋值运算符重载(注意深浅拷贝的问题)

注意

1.赋值前的对象堆区有数据应先释放

2.深浅拷贝的问题

#include<iostream>
#include<string>
using namespace std;class Person
{
private:string name;int* age;
public:Person(){}Person(string name, int a){this->name = name;this->age = new int(a);}~Person(){if (age != NULL){delete age;age = NULL;}}Person& operator=(Person& p){if (age != NULL){delete age;age = NULL;}this->age = new int(*p.age);this->name = p.name;return *this;}};int main()
{Person p1("叶盛",18);Person p2;Person p3;p3 = p2 = p1;return 0;
}

函数调用运算符重载和匿名函数对象

  • 函数调用运算符 () 也可以重载

  • 由于重载后使用的方式非常像函数的调用,因此称为仿函数

  • 仿函数没有固定写法,非常灵活

    class MyPrint
    {
    public:void operator()(string text){cout << text << endl;}};
    void test01()
    {//重载的()操作符 也称为仿函数MyPrint myFunc;myFunc("hello world");
    }class MyAdd
    {
    public:int operator()(int v1, int v2){return v1 + v2;}
    };void test02()
    {MyAdd add;int ret = add(10, 10);cout << "ret = " << ret << endl;//匿名对象调用  cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl;
    }int main() {test01();test02();system("pause");return 0; 
    }

    匿名函数对象

不创建仿函数对象,直接使用

仿函数类名()(参数1,参数2,参数3...)来执行函数 

继承

继承方式

 无论哪种继承方式都不能继承私有成员

公共继承:公共成员和保护成员不变,私有成员访问不到

保护继承:公共成员和保护成员均变为保护成员,私有成员访问不到

私有继承:公共成员和保护成员均变为私有成员,私有成员访问不到

从父类继承过来的成员,哪些属于子类对象中?

父类中私有成员也是被子类继承下去了,只是由编译器给隐藏后访问不到

父类和子类的构造和析构顺序是谁先谁后?

继承中 先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反

1.父类构造

2.子类构造

3.子类析构

4.父类析构

菱形继承(面试会考?)

两个派生类继承同一个基类

又有某个类同时继承者两个派生类

这种继承被称为菱形继承,或者钻石继承

  

  1. 羊继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据时,就会产生二义性。\

可以加作用域来解决:

st.Sheep::age=10;

st.Tuo::age=20;

     2.草泥马继承自动物的数据继承了两份,其实我们应该清楚,这份数据我们只需要一份就可以。

可以用虚继承解决菱形继承问题

虚继承——解决菱形问题

继承之前加上关键字virutal变为虚继承

exm:

class Sheep:virtual public Animal{.....
}

这里Animal类称为虚基类

示例

class Animal
{
public:int m_Age;
};//继承前加virtual关键字后,变为虚继承
//此时公共的父类Animal称为虚基类
class Sheep : virtual public Animal {};
class Tuo   : virtual public Animal {};
class SheepTuo : public Sheep, public Tuo {};void test01()
{SheepTuo st;st.Sheep::m_Age = 100;st.Tuo::m_Age = 200;cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;cout << "st.Tuo::m_Age = " <<  st.Tuo::m_Age << endl;cout << "st.m_Age = " << st.m_Age << endl;
}int main() {test01();system("pause");return 0;
}

底层原理

SheepTuo(羊驼)从Sheep(羊)类继承了一个vbptr(虚基类指针),从 Tuo(驼)类也继承了一个vbptr(虚基类指针),这两个指针分别指向一张虚基类表,表中有一个偏移量

两个地址(0、8)分别加上偏移量,指向同一个m_Age

多态(面试会问?)

 多态分为两类

  • 静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名

  • 动态多态: 派生类和虚函数实现运行时多态

静态多态和动态多态区别:

  • 静态多态的函数地址早绑定 - 编译阶段确定函数地址

  • 动态多态的函数地址晚绑定 - 运行阶段确定函数地址

动态多态条件:

1.有继承关系  eg:猫类继承动物类

2.子类重写父类的虚函数

3.父类的指针或者引用指向子类对象

重写:函数返回值类型、函数名、参数列表 完全相同

代码示例

#include<iostream>
using namespace std;class Animal
{
public:void doSpeak(){cout << "动物在说话." << endl;}
};class Cat :public Animal
{
public:void doSpeak(){cout << "小猫在说话." << endl;}
};void test01(Animal a)
{a.doSpeak();
}int main()
{Cat c;test01(c);return 0;
}

  输出结果

 分析

执行说话的函数

void test01(Animal a)
{a.doSpeak();
}

地址早绑定——在编译阶段就确定函数的地址

如果想执行让猫说话,则需要用虚函数(virtual)实现函数地址晚绑定(在运行阶段绑定)

原理剖析(重要)  

空类和不带虚函数的空类sizeof值为1,为什么?

#include<iostream>
using namespace std;
class Animal
{
public:void speak(){cout << "动物在说话!" << endl;}};int main()
{cout << "sizeof(Animal) = " << sizeof(Animal) << endl;return 0;
}

 

这里成员函数不属于该类,成员函数是共享的。

带虚函数的空类sizeof值为多少?为什么?

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

带一个虚函数的空类大小为8,这里是一个vfptr(虚函数)指针的大小,指向一个虚函数表。

虚函数实现多态原理剖析(重要)

#include<iostream>
using namespace std;
class Animal
{
public:virtual void speak(){cout << "动物在说话!" << endl;}};class Cat :public Animal
{};void test01(Animal& a)
{a.speak();
}int main()
{Cat cat;test01(cat);return 0;
}

动物类在内存中的结构为

PS:size这里为指针的大小,视频里为32位机,4个字节。

可以看到动物类有一个vfptr(虚函数指针)指向一张(vftable)虚函数表

表中有Animal类的speak函数地址

猫类继承了动物类,继承了一个虚函数指针指向自己的虚函数表,在没有重写speak函数之前,结构如下:

此时猫的虚函数表中存的是动物类的speak函数的地址

对speak函数进行重写后,猫的结构如下 

此时猫类的虚函数表中记录的是猫类的speak函数的地址。

 执行test01函数就会输出猫在叫。

纯虚函数和抽象类

概念

通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数.

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

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

抽象类特点

  • 无法实例化对象

  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类

代码示例

#include<iostream>
using namespace std;
class Animal
{
public:virtual void speak() = 0;};class Cat :public Animal
{void speak(){cout << "喵喵喵!" << endl;}
};void test01(Animal& a)
{a.speak();
}int main()
{Cat cat;test01(cat);return 0;
}

这里speak为纯虚函数,Animal为抽象类。

虚析构和纯虚析构

如果子类中有属性开辟到堆区,那么父类指针在释放时(delete父类指针)无法调用到子类的析构代码

虚析构和纯虚析构共性:

  • 可以解决父类指针释放子类对象

  • 都需要有具体的函数实现

虚析构和纯虚析构区别:

  • 如果是纯虚析构,该类属于抽象类,无法实例化对象

虚析构语法:

virtual ~类名(){}

纯虚析构语法:

virtual ~类名() = 0;

类名::~类名(){}

使用场景

#include<iostream>
#include<string>
using namespace std;class Animal
{
public:Animal(){cout << "动物类的构造函数调用." << endl;}virtual void speak(){cout << "动物在说话!" << endl;}~Animal(){cout << "动物类的析构函数调用." << endl;}
};class Cat :public Animal
{
public:Cat(string name){m_Name = new string(name);cout << "猫类的构造函数被调用." << endl;}string* m_Name;~Cat(){if (m_Name != NULL){delete m_Name;m_Name = NULL;}cout << "猫类的析构函数调用." << endl;}void speak(){cout <<*m_Name<< "猫在说话!" << endl;}
};void test01()
{Animal* cat = new Cat("Tom");delete cat;
}int main()
{test01();return 0;
}

输出结果

用父类(Animal)指针指向子类(Cat)对象cat,然后delete对象cat,结果只调用了父类(Animal)的析构函数,造成了内存泄漏。

解决

将父类中的析构函数改为虚析构或者纯虚析构

注意!无论是虚析构还是纯虚析构都要代码实现!

#include<iostream>
#include<string>
using namespace std;class Animal
{
public:Animal(){cout << "动物类的构造函数调用." << endl;}virtual void speak(){cout << "动物在说话!" << endl;}/*虚析构virtual ~Animal(){cout << "动物类的析构函数调用." << endl;}*///纯虚析构virtual ~Animal() = 0;
};//!纯虚析构函数也需要具体实现!
Animal::~Animal()
{cout << "动物类的析构函数调用." << endl;
}class Cat :public Animal
{
public:Cat(string name){m_Name = new string(name);cout << "猫类的构造函数被调用." << endl;}string* m_Name;~Cat(){if (m_Name != NULL){delete m_Name;m_Name = NULL;}cout << "猫类的析构函数调用." << endl;}void speak(){cout <<*m_Name<< "猫在说话!" << endl;}
};void test01()
{Animal* cat = new Cat("Tom");delete cat;
}int main()
{test01();return 0;
}

  

C++文件操作

笔记链接

C++文件操作-CSDN博客

职工管理系统

gitee项目地址

https://gitee.com/caodanxiao123/Employee-Management-System.git

遇到的问题

1.抽象类(含有纯虚函数)无法实例化,如何创建数组来存放该抽象类的子类对象?

可以创建抽象类指针的数组

 

2.注意命名空间问题,有的结构漏掉命名空间可能会报语法错误(太恶心了!!!)

注意:我的编程习惯是头文件的编写中不加using namespace std;有很多C++的结构是std命名空间的,如果漏掉std可能会报语法错误或者头文件和源文件不兼容的错误。

我在头文件中定义类ManagementSystem,有一个成员变量类型为fstream*

这个报错也是非常的抽象,最后问题是fstream没有加上命名空间std,编译器无法识别。

3.使用stringsteam拼接字符串

4.从文件中读取数据,这块真的恶心我半天,wcnm!!!

对于:

1.从文件中按行读取数据,getline有很多版本,fstream的getline,std命名空间下的getline研究用法太麻烦,以后暂时统一使用std命名空间下的getline(文件流 ,std::string )

2.对于字符串格式化也有很多种方法,以后统一使用C语言的sscanf_s

int sscanf_s(  const char *buffer,  const char *format,  ...  
);

buffer为要提取数据的字符串,format表示数据的格式,....后面用来接变量

char *形变量要指定长度

代码示例

从文本中读取数据

while (!ifs.eof())
{string line;getline(ifs,line);if (line == "")break;int ret = sscanf_s(line.c_str(), "no:%d\t\t\tname:%s\t\t\tpost:%s", &no, name, sizeof(name), post, sizeof(post));if (ret <= 0){cout << "员工数据库格式匹配失败." << endl;exit(1);}Staff* tmp;if (!strcmp(post, "普通员工")){tmp = new Employee(name);}else if (!strcmp(post, "经理")){tmp = new Manager(name);}else if (!strcmp(post, "老板")){tmp = new Boss(name);}s_v.push_back(tmp);}

格式化读取成员变量的值

int ret = sscanf_s(line.c_str(), "no:%d\t\t\tname:%s\t\t\tpost:%s", &no, name, sizeof(name), post, sizeof(post));
if (ret <= 0)
{cout << "员工数据库格式匹配失败." << endl;exit(1);
}

lambda表达式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/57376.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF中如何解决DataGrid的Header没有多余的一行

将最后一行设置DataGridTemplateColumn Width"*" 使其自适应

网站制作公司哪家比较靠谱?分享5家2024年口碑好的网站制作公司

想要分辨一家网站制作公司靠不靠谱并不简单&#xff0c;可能它流程透明&#xff0c;设计优秀。但这就一定是适合自己的吗&#xff1f;所以口碑这东西很重要。适合自己也很重要&#xff0c;要多方面去了解。 以下是五家在2024年口碑不错的网站制作公司&#xff0c;分享一下设计…

51单片机STC8G串口Uart配置

测试环境 单片机型号&#xff1a;STC8G1K08-38I-TSSOP20&#xff0c;其他型号请自行测试&#xff1b; IDE&#xff1a;KEIL C51&#xff1b; 寄存器配置及主要代码 STC8G系列单片机具有4个全双工异步串行通信接口&#xff1b;本文以串口1为例&#xff0c;串口1有4种工作方式…

像素、分辨率、PPI(像素密度)、帧率的概念

文章目录 前言一、像素1、定义2、像素点也不是越多越好 二、分辨率1、定义 三、PPI(像素密度)1、定义2、计算公式3、视网膜屏幕 四、帧率1、帧 (Frame)2、帧数 (Frames)3、帧率 (Frame Rate)4、FPS (Frames Per Second)5、赫兹 五、其他1、英寸2、为何显示器尺寸以英寸命名 总结…

Linux初阶——信号

一、预备 1、信号的处理方式 1.1. 默认动作 当收到一个信号时&#xff0c;就执行这个信号的默认动作。 1.2. 忽略 当收到一个信号时&#xff0c;就忽略执行这个信号的默认动作。 1.3. 自定义动作 当收到一个信号时&#xff0c;就执行信号的自定义动作。 2、硬件中断 你…

跨设备使用的便签软件哪款好?

在快节奏的现代生活中&#xff0c;便签软件已成为我们不可或缺的数字助手&#xff0c;它们帮助我们记录灵感、安排日程、设置提醒&#xff0c;极大地提升了我们的工作与生活效率。然而&#xff0c;面对市场上琳琅满目的便签应用&#xff0c;选择一款既实用又适合手机使用的便签…

【万兴科技-注册_登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

51单片机应用开发(进阶)---外部中断(按键+数码管显示0-F)

实现目标 1、巩固数码管、外部中断知识 2、具体实现&#xff1a;按键K4&#xff08;INT1&#xff09;每按一次&#xff0c;数码管从0依次递增显示至F&#xff0c;再按则循环显示。 一、共阳数码管 1.1 共阳数码管结构 1.2 共阳数码管码表 共阳不带小数点0-F段码为&#xff…

《链表篇》---两数相加(中等)

题目传送门 方法一&#xff1a;迭代 文字描述看代母注释 class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {//定义头结点和当前节点ListNode head null,cur null;//carry记录进位情况。int carry 0; while(l1 ! null || l2 ! null){//判断节点是…

Date工具类详细汇总-Date日期相关方法

# 1024程序员节 | 征文 # 目录 简介 Date工具类单元测试 Date工具类 简介 本文章是个人总结实际工作中常用到的Date工具类&#xff0c;主要包含Java-jdk8以下版本的Date相关使用方法&#xff0c;可以方便的在工作中灵活的应用&#xff0c;在个人工作期间频繁使用这些时间的格…

uniapp iOS打包证书过期——重新下载证书及更新文件

证书过期&#xff0c;重新生成步骤 关于所需的证书、标识符、描述文件等请查看iOS打包证书申请流程证书有效期为1年 过期提示 生成证书 点击 钥匙串访问 → 证书助理 → 从证书颁发机构请求证书 &#xff1b; 我这里选择 存储到磁盘 &#xff0c;邮件、名称 可自定义&#…

uniapp圆形波浪进度效果

uniapp圆形波浪进度效果 背景实现思路代码实现尾巴 背景 最近项目中有些统计的地方需要用到圆形的波浪进度效果&#xff0c;要求是根据百分比值然后在一个圆形内动态的展示一个波浪形的进度&#xff0c;看参考一下效果。 实现思路 这个效果看着挺复杂的&#xff0c;那么我们…

宠物空气净化器有用吗?有哪几款吸毛效果好且低噪的推荐

伴随着天气越来越凉&#xff0c;照常来说&#xff0c;猫咪掉毛的频率应该会变少&#xff0c;但是为什么我家的猫咪还在掉很多毛。 现在就连南方地区都要加外套了&#xff0c;但是猫咪掉毛太多&#xff0c;都不敢穿纯棉面料的衣服&#xff0c;还有本来想着顺应天气的变化&#…

深入理解C++ Lambda表达式:语法、用法与原理及其包装器的使用

深入理解C Lambda表达式&#xff1a;语法、用法与原理及其包装器的使用 lambda表达式C98中的一个例子lambda表达式语法lambda表达式各部分说明捕获列表说明 函数对象与lambda表达式 包装器function包装器 bind &#x1f30f;个人博客主页&#xff1a; 个人主页 本文深入介绍了…

2024最新Instagram养号攻略!海外社媒起号码住了

Instagram至今仍然是全球顶级的流量平合&#xff0c;不仅在国外是各大网红明星必备app&#xff0c;国内下载量也居高不下&#xff0c;但从2018年下半年开始加大了对新账号的监控和权限限制。新注册的账号会受到诸多限制&#xff0c;稍不慎就会进入安全模式或者被封&#xff0c;…

【vue】10.组件的生命周期-从Vue 2到Vue 3的演变

自Vue 2发布以来&#xff0c;它以其简单易用、灵活高效的特点赢得了众多开发者的喜爱。随着时间的推移&#xff0c;Vue 3在Vue 2的基础上进行了全面升级&#xff0c;其中包括对组件生命周期的调整。本文将首先回顾Vue 2的组件生命周期&#xff0c;然后重点介绍Vue 3组件生命周期…

STM32 HAL 点灯

首先从点灯开始 完整函数如下&#xff1a; #include "led.h" #include "sys.h"//包含了stm32f1xx.h&#xff08;包含各种寄存器定义、中断向量定义、常量定义等&#xff09;//初始化GPIO口 void led_init(void) {GPIO_InitTypeDef gpio_initstruct;//打开…

计算合约方法的签名

计算合约方法的签名 通过智能合约实现 // SPDX-License-Identifier: MIT pragma solidity ^0.8.26;contract FunctionSelector {/*"transfer(address,uint256)"0xa9059cbb"transferFrom(address,address,uint256)"0x23b872dd*/function getSelector(stri…

【Java】方法的使用 —— 语法要求、方法的重载和签名、方法递归

目录 1. 方法基础知识 1.1 方法的概念 1.2 语法格式 * 注意事项【与C不同】 1.3 return —— 返回值的严格检查【比C语言严格】 2. 形参与实参的关系 3. 方法重载 3.1 什么是方法重载&#xff1f;为什么要方法重载&#xff1f; 3.2 方法重载的规则 4. 方法签名 5. 递…

鸿蒙开发:arkts Refresh 组件

基本概念 在 ArkTS 5.0 中&#xff0c;Refresh组件是用于实现下拉刷新功能的重要元素。它为用户提供了一种直观的方式来获取最新的数据。当用户在界面上对Refresh组件所在的区域进行下拉操作时&#xff0c;如果满足一定的触发条件&#xff0c;就会触发刷新事件&#xff0c;从而…