C++ 友元、重载、继承、多态

news2024/12/22 22:43:01

友元

关键字:friend

友元的三种实现

  • 全局函数做友元
  • 类做友元
  • 成员函数做友元
全局函数做友元
//建筑物类
class Building
{
    //goodGay全局函数是Building好朋友,可以访问Building中私有成员
    friend void goodGay(Building& building);
public:
    Building()
    {
        m_SittingRoom = "客厅";
        m_bedRoom = "卧室";
    }
    string m_SittingRoom;
private:
    string m_bedRoom;
};
//全局函数
void goodGay(Building& building)
{
    cout << "好基友全局函数正在访问:" << building.m_SittingRoom << endl;
    cout << "好基友全局函数正在访问:" << building.m_bedRoom << endl;

}
void test01()
{
    Building building;
    goodGay(building);
}
类做友元
class Building;
class goodGay;
class goodGay
{
public:
    goodGay();
    void visit();
private:
    Building* building;
};
//建筑物类
class Building
{  
    friend class goodGay;
public:
    Building();
    string m_SittingRoom;
private:
    string m_bedRoom;
};
Building::Building()
{
    this->m_SittingRoom = "客厅";
    this->m_bedRoom = "卧室";
}
goodGay::goodGay()
{
    building = new Building;
}
void goodGay::visit()
{
    cout << "好基友全局函数正在访问:" << building->m_SittingRoom << endl;
    cout << "好基友全局函数正在访问:" << building->m_bedRoom << endl;
}

void test01()
{
    goodGay gg;
    gg.visit();
}
成员函数做友元
class Building;
class goodGay;
class goodGay
{
public:
    goodGay();
    void visit();
    void visit2();//只让visit访问私有属性,visit2不能访问
private:
    Building* building;
};
//建筑物类
class Building
{  
    friend void goodGay::visit();
public:
    Building();
    string m_SittingRoom;
private:
    string m_bedRoom;
};
Building::Building()
{
    this->m_SittingRoom = "客厅";
    this->m_bedRoom = "卧室";
}
goodGay::goodGay()
{
    building = new Building;
}
void goodGay::visit()
{
    cout << "好基友全局函数正在访问:" << building->m_SittingRoom << endl;
    cout << "好基友全局函数正在访问:" << building->m_bedRoom << endl;
}
void goodGay::visit2()
{
    cout << "好基友全局函数正在访问:" << building->m_SittingRoom << endl;
    //cout << "好基友全局函数正在访问:" << building->m_bedRoom << endl;
}

void test01()
{
    goodGay gg;
    gg.visit();
   
}

重载

运算符重载
加号运算符重载

成员函数重载
class Person
{
public:
    //1. 成员函数重载+号
    Person operator+(Person& p)
    {
        Person temp;
        temp.m_A = this->m_A + p.m_A;
        temp.m_B = this->m_B + p.m_B;
        return temp;
    }
    int m_A;
    int m_B;
};
void test01()
{
    Person p1;
    p1.m_A = 10;
    p1.m_B = 10;
    Person p2;
    p2.m_A = 10;
    p2.m_B = 10;

    //成员函数重载本质调用
    //Person p3 = p1.operator+(p2);
    Person p3 = p1 + p2;
    cout << "m_A:" << p3.m_A << ", m_B:" << p3.m_B << endl;

}
全局函数重载和函数重载
class Person
{
public:
    int m_A;
    int m_B;
};
//2. 全局函数重载+号
Person operator+(Person& p1, Person& p2)
{
    Person temp;
    temp.m_A = p1.m_A + p2.m_A;
    temp.m_B = p1.m_B + p2.m_B;
    return temp;
}
//函数重载的版本
Person operator+(Person& p1, int num)
{
    Person temp;
    temp.m_A = p1.m_A + num;
    temp.m_B = p1.m_B + num;
    return temp;

}
void test01()
{
    Person p1;
    p1.m_A = 10;
    p1.m_B = 10;
    Person p2;
    p2.m_A = 10;
    p2.m_B = 10;

    //全局函数重载本质调用
    //Person p3 = operator+(p1, p2);
    Person p3 = p1 + p2;

    //运算符重载 也可以发生函数重载
    Person p4 = p1 + 100;
    cout << "m_A:" << p3.m_A << ", m_B:" << p3.m_B << endl;
    cout << "m_A:" << p4.m_A << ", m_B:" << p4.m_B << endl;

}

总结1:对于内置的数据类型的表达式的运算符是不可能改变的

总结2:不要滥用运算符重载

左移运算符重载

只能利用全局函数重载左移运算符,因为如果利用成员函数重载,左移运算符 p.operator<<(cout) 简化版本为p<<cout,无法实现cout在左侧

重载运算符目的:只输出对象p就可以实现输出p中的所有成员属性。

class Person
{
    friend ostream& operator<<(ostream& cout, Person& p);
public:
    Person(int a, int b)
    {
        m_A = a;
        m_B = b;
    }
private:
    int m_A;
    int m_B;
};
// 只能利用全局函数重载左移运算符
ostream& operator<<(ostream& cout, Person& p)//本质:operstor(cout, p)
{
    cout << "m_A = " << p.m_A << ", m_B = " << p.m_B;
    return cout;
}

void test01()
{
    Person p(10, 10);
    cout << p << endl;
}
递增运算符重载
class MyInteger
{
    friend ostream& operator<<(ostream& cout, MyInteger myint);
public:
    //重载前置++运算符,返回引用为了一直对一个数据进行递增操作
    MyInteger& operator++()
    {
        //先进行++运算
        m_Num++;
        //再将自身做返回
        return *this;
    }
    //重载后置++运算符
    //void operator++(int)  
	//int代表占位参数,可以用于区分前置和后置递增
    MyInteger operator++(int)
    {
        //先 记录当时结果
        MyInteger temp = *this;
        //后 递增
        m_Num++;
        //最后将记录结果做返回
        return temp;

    }
    MyInteger(int num)
    {
        m_Num = num;
    }
private:
    int m_Num;
};

ostream& operator<<(ostream& cout, MyInteger myint)
{
    cout << myint.m_Num << endl;
    return cout;
}

void test01()
{
    MyInteger myint(0);
    cout << ++(++myint);
    cout << myint;
    cout << myint++;
    cout << myint;
}

总结:前置递增返回引用,后置递增返回值。

赋值运算符重载
class Person
{
public:
    Person(int age);
    ~Person();
    Person& operator=(Person& p);
    int* m_Age;
};
Person::Person(int age)
{
    //将年龄数据开辟到堆区
    m_Age = new int(age);
}
Person::~Person()
{
    if (m_Age != NULL)
    {
        delete m_Age;
        m_Age = NULL;
    }
}
//重载 赋值运算符
Person& Person::operator=(Person& p)
{
    //编译器是提供浅拷贝
    //m_Age = p.m_Age;
    //应该先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
    if (m_Age != NULL)
    {
        delete m_Age;
        m_Age = NULL;
    }
    //深拷贝
    m_Age = new int(*p.m_Age);
    //返回对象本身
    return *this;
}
void test01()
{
    Person p1(18);
    Person p2(20);
    Person p3(25);
    p1 = p2 = p3;
    cout << "p1年龄:" << *p1.m_Age << endl;
    cout << "p2年龄:" << *p2.m_Age << endl;
    cout << "p3年龄:" << *p3.m_Age << endl;

}
关系运算符重载

作用:重载关系运算符,可以让两个自定义类型对象进行对比操作

class Person
{
public:
    Person(string name, int age);
    bool operator==(Person& p);
    bool operator!=(Person& p);

private:
    string m_Name;
    int m_Age;
};

Person::Person(string name, int age)
{
    m_Name = name;
    m_Age = age;
}
bool Person::operator==(Person& p)
{
    if (m_Name == p.m_Name && m_Age == p.m_Age)
    {
        return true;
    }
    return false;
}
bool Person::operator!=(Person& p)
{
    if (m_Name == p.m_Name && m_Age == p.m_Age)
    {
        return false;
    }
    return true;
}
void test01()
{
    Person p1("Bob", 18);
    Person p2("Bob", 20);
    if (p1 != p2)
    {
        cout << "p1和p2不相等!" << endl;
    }
    else
    {
        cout << "p1和p2相等!" << endl;
    }
}
函数调用运算符重载
  • 函数调用运算符()也可以重载
  • 由于重载后使用的方式非常像函数的调用,因此称为仿函数
  • 仿函数没有固定写法,非常灵活

重定义可打印函数和可加函数

class MyPrint
{
public:
    void operator()(string text);
private:

};
void MyPrint::operator()(string text)
{
    cout << text << endl;
}
class MyAdd
{
public:
    int operator()(int num1, int num2)
    {
        int ret = num1 + num2;
        return ret;
    }

private:

};


void test01()
{
    MyPrint myprint;
    myprint("hello world!"); //由于使用起来非常类似于函数调用,因此称为仿函数

    MyAdd myadd;
    int ret = myadd(10, 20);
    cout << "ret=" << ret << endl;

    //匿名对象
    cout << MyAdd()(23, 23) << endl;

}

继承

继承是面向对象三大特性之一

继承的好处:减少重复代码

语法 --- class 子类:继承方式

子类 也称为 派生类

父类 也称为 基类

class A: public B;

继承方法
  • 公共继承
  • 保护继承
  • 私有继承

继承中的对象模型

父类中所有非静态成员属性都会被子类继承下去

父类中私有成员属性,是被编译器给隐藏了,因此是访问不到,但确实被继承下去了

使用开发工具查看对象模型:

打开工具窗口,定位到当前cpp文件的盘符,然后输入:

cl /d1 reportSingleClassLayout查看的类名 所属文件名

继承中构造和析构顺序

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

子类和父类同名成员处理

子类对象可以直接访问到子类中同名成员

如果通过子类对象 访问到父类中同名成员,需要加作用域

如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数

如果想访问到父类中被隐藏的同名成员函数,需要加作用域

多继承语法

C++允许一个类继承多个类

语法:class 类:继承方式 父类1,继承方式 父类2

class Son: public Base1, public Base2

{}

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

C++实际开发中不建议用多继承

菱形继承
菱形继承概念

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

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

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

典型菱形继承案例

菱形继承问题
  • 菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义
  • 利用虚继承可以解决菱形继承的问题

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

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 = 18;
    st.Tuo::m_Age = 21;
    //当菱形继承,两个父类拥有相同属性,需要加以作用域区分
    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;
}

多态

多态的基本概念

多态是C++面向对象三大特性之一

多态分为两类

  • 静态多态:函数重载和运算符重载属于静态多态,复用函数名
  • 动态多态:派生类和虚函数实现运行时多态

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

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

动态多态满足条件:

  1. 有继承关系
  2. 子类重写父类的虚函数

动态多态的使用:

父类的指针或引用,指向子类对象

class Animal
{
public:
    //虚函数
    virtual void speak()
    {
        cout << "动物在说话!" << endl;
    }
};

//猫类
class Cat : public Animal
{
public:
    //重写 函数返回值类型 函数名 参数列表 完全相同
    void speak()
    {
        cout << "小猫在说话!" << endl;
    }
};
class Dog : public Animal
{
public:
    void speak()
    {
        cout << "小狗在说话!" << endl;
    }
};
//执行说话的函数 虽然传入Cat,但是还是动物说话,因为地址早绑定,在编译阶段确定函数地址
//如果想执行让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段绑定,地址晚绑定
//解决方法:virtual 虚函数
void doSpeak(Animal& animal)
{
    animal.speak();
}

void test01()
{
    Cat cat;
    doSpeak(cat);
    Dog dog;
    doSpeak(dog);
}
多态原理

多态案例 - 计算机类

案例描述:分别利用普通写法和多态技术,设计实现两个操作数进行运算的计算机类

多态的优点:

  • 代码组织结构清晰
  • 可读性强
  • 利于前期和后期的扩展以及维护
传统写法
//传统计算器写法
class Calculator
{
public:
    int getResult(string oper)
    {
        if (oper == "+")
        {
            return num1 + num2;
        }
        else if (oper == "-")
        {
            return num1 - num2;
        }
        else if (oper == "*")
        {
            return num1 * num2;
        }
        //如果要提供新的运算,需要修改源码
    }
    int num1;
    int num2;
};
void test01()
{
    Calculator c;
    c.num1 = 10;
    c.num2 = 10;
    cout << c.num1 << "+" << c.num2 << "=" << c.getResult("+") << endl;
    cout << c.num1 << "-" << c.num2 << "=" << c.getResult("-") << endl;
    cout << c.num1 << "*" << c.num2 << "=" << c.getResult("*") << endl;
}
多态写法
//利用多态写计算器
//多态好处:
//1. 组织结构清晰
//2. 可读性强
//3. 对于前期和后期扩展以及维护性高

//实现计算器抽象类
class AbstractCalculator
{
public:
    virtual int getResult()
    {
        return 0;
    }
    int num1;
    int num2;
};
//加法计算器类
class AddCalculator: public AbstractCalculator
{
public:
    int getResult()
    {
        return num1 + num2;
    }
};
//乘法计算器类
class MulCalculator : public AbstractCalculator
{
public:
    int getResult()
    {
        return num1 * num2;
    }
};
//减法计算器类
class SubCalculator : public AbstractCalculator
{
public:
    int getResult()
    {
        return num1 - num2;
    }
};

void test02()
{
    //多态使用条件
    //父类指针或引用指向子类对象
    AbstractCalculator* c = new AddCalculator;
    c->num1 = 10;
    c->num2 = 10;
    cout << c->num1 << "+" << c->num2 << "=" << c->getResult() << endl;
    delete c;
    SubCalculator a;
    AbstractCalculator& m = a;
    m.num1 = 20;
    m.num2 = 20;
    cout << m.num1 << "-" << m.num2 << "=" << m.getResult() << endl;
}
纯虚函数和抽象类

在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容

因此可以将虚函数改为纯虚函数

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

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

抽象类特点:

  • 无法实例化对象
  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类
//纯虚函数
//只要有一个纯虚函数,这个类称为抽象类
class Base
{
public:
    virtual void func() = 0;
};
class Son: public Base
{
public:
    void func()
    {

    }
};

void test01()
{
    //抽象类无法实例化对象
    //Base b; 
    //new Base;
    //Son s; //子类必须重写父类中的纯虚函数,否则无法实例化对象
    Base* base = new Son;
    base->func();
}
多态案例2 - 制作饮品

案例描述:

制作饮品大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料

利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶

class AbstractDrink
{
public:
    //煮水
    virtual void boil() = 0;
    //冲泡
    virtual void brew() = 0;
    //倒入杯中
    virtual void pour() = 0;
    //加入辅料
    virtual void addSomething() = 0;
    //制作饮品
    void makeDrink()
    {
        boil();
        brew();
        pour();
        addSomething();

    }
};
//制作咖啡
class Coffee : public AbstractDrink
{
public:
    void boil()
    {
        cout << "煮矿泉水" << endl;
    }
    void brew()
    {
        cout << "冲泡咖啡" << endl;
    }
    void pour()
    {
        cout << "倒入咖啡杯中" << endl;
    }
    void addSomething()
    {
        cout << "加糖和牛奶" << endl;
    }
};
//制作茶叶
class Tea : public AbstractDrink
{
public:
    void boil()
    {
        cout << "煮水" << endl;
    }
    void brew()
    {
        cout << "冲泡茶叶" << endl;
    }
    void pour()
    {
        cout << "倒入茶杯中" << endl;
    }
    void addSomething()
    {
        cout << "加柠檬" << endl;
    }
};
//制作函数
void doWork(AbstractDrink* abs)
{
    abs->makeDrink();
    delete abs;
}
void test01()
{
    //制作咖啡
    doWork(new Coffee);
    cout << "-----------------------------------------" << endl;
    //制作茶叶
    doWork(new Tea);
}
虚析构和纯虚析构

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

解决方式:将父类中的析构函数改为虚析构纯虚析构

虚析构和纯虚析构共性:

  • 可以解决父类指针释放子类对象
  • 都需要有具体的函数实现

虚析构和纯虚析构区别:

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

虚析构语法:

virtual ~类名(){}

纯虚析构语法:

virtual ~类名()=0;

class Animal
{
public:
    virtual void speak() = 0;
    Animal()
    {
        cout << "animal构造函数调用" << endl;
    }
    ~Animal()
    {
        cout << "animal析构函数调用" << endl;
    }
};
class Cat : public Animal
{
public:
    Cat(string name)
    {
        m_name = new string(name);
        cout << "cat构造函数调用" << endl;
    }
    ~Cat()
    {
        if (m_name != NULL)
        {
            cout << "Cat析构函数调用" << endl;
            delete m_name;
            m_name = NULL;
        }  
    }
    void speak()
    {
        cout <<*m_name<< "小猫在说话" << endl;
    }
    string* m_name;
};
void test01()
{
    Animal* cat = new Cat("Tom");
    cat->speak();
    //父类指针在析构的时候,不会调用子类中析构函数
    //导致子类如果有堆区属性,出现内存泄漏
    delete cat;
}

上面代码无法调用cat的析构函数

将父类的析构函数变为虚函数即可访问子类析构函数。

class Animal
{
public:
    //纯虚函数
    virtual void speak() = 0;
    Animal()
    {
        cout << "animal构造函数调用" << endl;
    }
    //利用虚析构可以解决 父类指针释放子类对象时不干净的问题
    /*virtual ~Animal()
    {
        cout << "animal析构函数调用" << endl;
    }*/
    //纯虚析构
    virtual ~Animal();

};
Animal::~Animal()
{
    cout << "animal纯析构函数调用" << endl;
}
class Cat : public Animal
{
public:
    Cat(string name)
    {
        m_name = new string(name);
        cout << "cat构造函数调用" << endl;
    }
    ~Cat()
    {
        if (m_name != NULL)
        {
            cout << "Cat析构函数调用" << endl;
            delete m_name;
            m_name = NULL;
        }
        
        
    }
    void speak()
    {
        cout <<*m_name<< "小猫在说话" << endl;
    }
    string* m_name;
};
void test01()
{
    Animal* cat = new Cat("Tom");
    cat->speak();
    delete cat;

}

总结:

  1. 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
  2. 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构
  3. 拥有纯虚析构函数的类也属于抽象类
多态案例3 - 电脑组装

private:
    CPU* m_cpu;
    VideoCard* m_videoCard;
    Memory* m_memory;
};
class IntelCpu : public CPU
{
public:
    void calculate()
    {
        cout << "Intel的CPU正在计算。。。。。。" << endl;
    }
};
class IntelVc : public VideoCard
{
public:
    void display()
    {
        cout << "Intel显卡正在显示。。。。。。" << endl;
    }
};
class IntelMem : public Memory
{
public:
    void storage()
    {
        cout << "Intel的内存条正在存储。。。。。。" << endl;
    }
};

class LenovoCpu : public CPU
{
public:
    void calculate()
    {
        cout << "Lenovo的CPU正在计算。。。。。。" << endl;
    }
};
class LenovoVc : public VideoCard
{
public:
    void display()
    {
        cout << "Lenovo显卡正在显示。。。。。。" << endl;
    }
};
class LenovoMem : public Memory
{
public:
    void storage()
    {
        cout << "Lenovo的内存条正在存储。。。。。。" << endl;
    }
};


void test01()
{
    Computer* computer1 = new Computer(new IntelCpu, new IntelVc, new IntelMem);
    Computer* computer2 = new Computer(new LenovoCpu, new LenovoVc, new LenovoMem);
    Computer* computer3 = new Computer(new IntelCpu, new IntelVc, new LenovoMem);
    computer1->doWork();
    cout << "-------------------------------------" << endl;
    computer2->doWork();
    cout << "-------------------------------------" << endl;
    computer3->doWork();
    delete computer1;
    delete computer2;
    delete computer3;
}

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

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

相关文章

人才测评系统在企业招聘中的应用

人才测评作为招聘工具&#xff0c;已经频繁应用在各大企业中&#xff0c;如今的社会中&#xff0c;人才对于企业而言&#xff0c;可谓是创造产值的基础。换句话说&#xff0c;”企业得人才者、才能得天下”&#xff0c;有了人才之后&#xff0c;企业在行业中才有竞争力。 目前…

Lnmp架构之Redis服务

1、redis部署 停掉mysql服务 如果在纯净的环境下&#xff0c;make的时候需要安装gcc和make redis服务常用命令 2、redis主从同步 复制文件发送到接收主机server2&#xff0c;server3 server2&#xff0c;server3接收到文件后&#xff0c;和11master端一样的配置方法 3、redis主…

网络机顶盒哪个牌子好?经销商盘点线下畅销网络电视机顶盒排名

网络机顶盒是生活必备小家电&#xff0c;我店内经营网络机顶盒已经很多年了&#xff0c;对这个行业有着深入研究&#xff0c;近来看到网友们在讨论网络机顶盒哪个牌子好&#xff0c;我根据店内销量情况&#xff0c;整理了实体店铺热销网络电视机顶盒排名&#xff0c;感兴趣的朋…

循环神经网络——中篇【深度学习】【PyTorch】【d2l】

文章目录 6、循环神经网络6.4、循环神经网络&#xff08;RNN&#xff09;6.4.1、理论部分6.4.2、代码实现 6.5、长短期记忆网络&#xff08;LSTM&#xff09;6.5.1、理论部分6.5.2、代码实现 6.6、门控循环单元&#xff08;GRU&#xff09;6.6.1、理论部分6.6.2、代码实现 6、循…

实现电商跨平台订单每日自动对账

场景描述&#xff1a; 多数商家都存在多电商平台同时经营的情况&#xff0c;而进行订单对账则是相关业务或财务人员的每日必修课。比如商家在天猫&#xff0c;苏宁&#xff0c;1号店&#xff0c;京东等均有运营店铺&#xff0c;每天需要通过各电商后台系统抓单打单&#xff0c…

Android 小组件 AppWidgetProvider

一、相关文档 二、小组件是什么&#xff1f; 三、AppWidget 核心类 AppWidgetProvider 源码解读和原理分析 1、先看 AppWidgetProvider 源码 2、AppWidgetProvider 回调方法分析 onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appW…

索引与切片

索引 生成一个CNN的输入格式张量 a torch.rand(4, 3, 28, 28) &#xff08;batch, channel&#xff0c;high, width)单个索引的方式与python一样 a[0] # 去索引为0的图片即第一张图片 a[0].shape多个索引与python稍微不一样&#xff0c;但很相似 python&#xff1a;a[0][0…

PMP证书在国内已经泛滥了,还有含金量吗?

没有泛滥吧&#xff1f;这个证书现在就是趋向于项目管理人士要去考的呀&#xff0c;也不是考了没用&#xff0c;提升自身个人的能力、找工作方面和晋升加薪方面确实有用呀&#xff0c;不然报名费那么贵&#xff0c;为什么越来越多人考呢&#xff1f; 1、提升自身个人的能力 首…

云原生技术盛会KubeCon即将召开!亚马逊云科技作为钻石赞助商参会

KubeCon2023将于9月26-28日在上海跨国采购会展中心隆重召开。作为云原生领域最负盛名的技术大会之一&#xff0c;KubeConCloudNativeCon是连接全球开发者与云原生社区的最佳平台&#xff0c;此次还新增Open Source Summit环节&#xff0c;吸引了全球顶尖的云原生专家们汇聚其中…

利用C++开发一个迷你的英文单词录入和测试小程序-增强功能

小玩具基本完成之后&#xff0c;在日常工作中&#xff0c;记录一些单词&#xff0c;然后定时再复习下&#xff0c;还真的有那么一点点用&#xff08;毕竟自己做的小玩具&#xff09;。 在使用过程中&#xff0c;遇到不认识的单词&#xff0c;总去翻译软件翻译&#xff0c;然后…

结合Mockjs与Bus事件总线搭建首页导航和左侧菜单

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《ELement》。&#x1f3af;&#x1f3af; &#x1…

可在电脑桌面显示每日工作计划表的工具用哪个?

当你坐在电脑前&#xff0c;繁忙的工作日开始了。屏幕前的任务排成一列&#xff0c;待处理的事情如潮水般涌来。这时&#xff0c;你需要一款强大的工具来帮助你合理安排时间&#xff0c;确保没有一个任务被忘记。 在这个数字时代&#xff0c;有一款工具可以在你的电脑桌面上显…

关于建筑八大员(住建厅七大员)考试难不难?合格技巧

关于建筑八大员&#xff08;住建厅七大员&#xff09;考试难不难&#xff1f;合格技巧 建筑八大员分为施工员、质量员、资料员、材料员、机械员、劳务员、标准员等7种大类。电脑考核&#xff0c;系统好几万题目&#xff0c;随机抽取一套匹配给你&#xff0c;每个人考试题目都不…

数组01-二分查找算法

目录 数组如何实现随机访问 两个关键词 数组的特点 根据下标随机访问数组元素 为什么数组要从0开始编号&#xff0c;而不是从1开始 LeetCode之路——704. 二分查找 Code 二分查找算法 数组如何实现随机访问 数组&#xff08;Array&#xff09;是一种线性表数据结构。它…

【从0学习Solidity】51. ERC4626 代币化金库标准

【从0学习Solidity】51. ERC4626 代币化金库标准 博主简介&#xff1a;不写代码没饭吃&#xff0c;一名全栈领域的创作者&#xff0c;专注于研究互联网产品的解决方案和技术。熟悉云原生、微服务架构&#xff0c;分享一些项目实战经验以及前沿技术的见解。关注我们的主页&#…

https跳过SSL认证时是不是就是不加密的,相当于http?

https跳过SSL认证时是不是就是不加密的,相当于http?&#xff0c;其实不是&#xff0c;HTTPS跳过SSL认证并不相当于HTTP&#xff0c;也不意味着没有加密。请注意以下几点&#xff1a; HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;本质上是在HTTP的基础上…

在docker中删除none镜像

在构建过Docker镜像的电脑上查看本地镜像列表&#xff0c;有可能看到下图红框中的镜像&#xff0c;在列表中展示为:&#xff1a; 这种镜像在Docker官方文档中被称作dangling images&#xff0c;指的是没有标签并且没有被容器使用的镜像。 官方解释 来自官方的解释如下图红框所…

【多线程初阶】多线程案例之阻塞式队列

文章目录 前言1. 什么是阻塞队列2. 生产者消费者模型2.1 生产者消费者模型的优势2.1.1 解耦合2.1.2 削峰填谷 3. Java 标准库中的阻塞队列3.1 生产者消费者模型 4. 自己实现一个阻塞队列总结 前言 本文主要给大家讲解多线程的一个重要案例 — 阻塞式队列. 关注收藏, 开始学习…

如何在Windows11上使用macOS Sonoma全新的慢镜屏幕保护程序

前言 macOS Sonoma是Apple macOS一个大版本的描述&#xff0c;以任何方式使用macOS Sonoma都应确保符合Apple的规定 本文假定你在搭载Intel处理器的Apple产品上通过bootcamp安装了Windows11&#xff0c;且想要让Windows11产生类似于macOS Sonoma全新的慢镜屏幕保护程序的相关…

java面试题-jvm基础知识

1 JVM组成 1.1 JVM由那些部分组成&#xff0c;运行流程是什么&#xff1f; 难易程度&#xff1a;☆☆☆ 出现频率&#xff1a;☆☆☆☆ JVM是什么 Java Virtual Machine Java程序的运行环境&#xff08;java二进制字节码的运行环境&#xff09; 好处&#xff1a; 一次编写&a…