(十)C++类和对象之多态

news2024/10/23 0:03:24

文章目录

  • 4 类和对象
    • 4.7 多态
      • 4.7.1 多态的基本介绍
      • 4.7.2 纯虚函数和抽象类
      • 4.7.3 虚析构和纯虚析构
      • 4.7.4 多态案例一-计算器类
      • 4.7.5 多态案例二-制作饮品
      • 4.7.6 多态案例三-电脑组装
      • 4.7.7 继承与多态案例

4 类和对象


4.7 多态


4.7.1 多态的基本介绍


1.多态的基本语法

C++ 重写:virtual 函数值返回类型 函数名 参数列表

2.多态满足条件

  • 有继承关系
  • 子类重写父类中的虚函数

3.多态使用条件

  • 父类指针或引用指向子类对象

4.多态的优点

  • 代码组织结构清晰
  • 可读性强
  • 利于前期和后期的扩展以及维护

例4.7.1 class animal

#include <iostream>

using namespace std;

// 多态

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

// 猫类
class Cat :public Animal
{
public:
    // 重写 函数返回值类型 函数名 参数列表 完全相同
    virtual void speak()
    {
        cout << "小猫在说话" << endl;
    }
};

// 狗类
class Dog :public Animal
{
public:
    // 重写 函数返回值类型 函数名 参数列表 完全相同
    virtual void speak()
    {
        cout << "小狗在说话" << endl;
    }
};

// 执行说话的函数
// 地址早已绑定 在编译阶段确定函数地址
// 如果想执行让猫说话,那么这个函数不能提前绑定,要在运行阶段进行绑定,地址晚绑定
void doSpeak(Animal &animal) // Animal & animal == cat;
{
    animal.speak();
}

void test01()
{
    Cat cat;
    doSpeak(cat);
    Dog dog;
    doSpeak(dog);
}
int main()
{
    test01();
    return 0;
}

​ 结果如下:

小猫在说话
小狗在说话

Process returned 0 (0x0)   execution time : 0.085 s
Press any key to continue.

4.7.2 纯虚函数和抽象类


​ 在多态中,通常父类中的虚函数的实现是没有意义的,主要是调用子类重写的内容,因此可以将虚函数改为纯虚函数。

​ 纯虚函数的语法:

virtual 返回值类型 函数名 (形参列表) = 0;

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

​ 抽象类的特点

  • 无法实例化对象
  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类

例4.7.2

#include <iostream>

using namespace std;

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

};

class Son :public Base
{
public:
    virtual void func()
    {
        cout << "output the son result" << endl;
    }
};

void test01()
{
    // Base b; // 抽象类无法实例化对象
    // new Base; // 抽象类无法实例化对象
    Son s; // 子类必须重写父类中的纯虚函数,否则无法实现实例化对象。

    Base * base = new Son;
    base->func();
}

int main()
{
    test01();
    return 0;
}

​ 结果如下:

output the son result

Process returned 0 (0x0)   execution time : 0.083 s
Press any key to continue.

4.7.3 虚析构和纯虚析构


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

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

​ 虚析构和纯虚析构的共性:

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

​ 纯虚析构和虚析构的区别:

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

​ 虚析构语法:

c++ virtual ~类名() { ... }

​ 纯虚析构的语法:

C++ virtual ~类名() = 0;
类名::类名() { ... }

例4.7.3.1 调用虚析构函数

#include <iostream>
#include <string>
using namespace std;

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

    // 纯虚函数
    virtual void speak() = 0;

};

/*Animal::~Animal()
{
    cout << "Animal的纯虚析构函数调用" << endl;
}*/

class Cat :public Animal
{
public:
    Cat(string name)
    {
        cout << "Cat的构造函数调用" << endl;
        m_Name = new string (name);
    }
    virtual void speak()
    {
        cout << *m_Name << "小猫在说话" << endl;
    }
    ~Cat()
    {
        if (m_Name != NULL)
        {
            cout << "Cat的虚析构函数调用" << endl;
            delete m_Name;
            m_Name = NULL;
        }
    }
    string *m_Name;
};

void test01()
{
    Animal * animal = new Cat("Tom");
    animal->speak();
    // 父类指针在析构的时候 不会调用子类中的析构函数,导致子类如果有堆区属性,出现内存泄露
    delete animal;
}
int main()
{
    test01();
    return 0;
}

​ 结果如下:

Animal的构造函数调用
Cat的构造函数调用
Tom小猫在说话
Cat的虚析构函数调用
Animal的虚析构函数调用

Process returned 0 (0x0)   execution time : 0.113 s
Press any key to continue.

例4.7.3.2 调用纯虚析构函数

#include <iostream>
#include <string>
using namespace std;

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

    // 纯虚函数
    virtual void speak() = 0;

};

Animal::~Animal()
{
    cout << "Animal的纯虚析构函数调用" << endl;
}

class Cat :public Animal
{
public:
    Cat(string name)
    {
        cout << "Cat的构造函数调用" << endl;
        m_Name = new string (name);
    }
    virtual void speak()
    {
        cout << *m_Name << "小猫在说话" << endl;
    }
    ~Cat()
    {
        if (m_Name != NULL)
        {
            cout << "Cat的虚析构函数调用" << endl;
            delete m_Name;
            m_Name = NULL;
        }
    }
    string *m_Name;
};

void test01()
{
    Animal * animal = new Cat("Tom");
    animal->speak();
    // 父类指针在析构的时候 不会调用子类中的析构函数,导致子类如果有堆区属性,出现内存泄露
    delete animal;
}
int main()
{
    test01();
    return 0;
}

​ 结果如下:

Animal的构造函数调用
Cat的构造函数调用
Tom小猫在说话
Cat的虚析构函数调用
Animal的纯虚析构函数调用

Process returned 0 (0x0)   execution time : 0.029 s
Press any key to continue.

4.7.4 多态案例一-计算器类


例4.7.4 class calculator

#include <iostream>
#include <string>

using namespace std;

// 分别利用基本写法和多态技术实现计算器

// 普通写法
class Calculator
{
public:
    int getResult(string oper)
    {
        if(oper == "+")
        {
            return m_Num1 + m_Num2;
        }
        else if(oper == "-")
        {
            return m_Num1 - m_Num2;
        }
        else if(oper == "*")
        {
            return m_Num1 * m_Num2;
        }
        else if(oper == "/")
        {
            return m_Num1 / m_Num2;
        }
    }
    int m_Num1;
    int m_Num2;
    // 如果想拓展新的功能,需要修改源码
    // 在真实开发中提倡开闭原则
    // 开闭原则:对扩展进行开发,对修改进行关闭
};

void test01()
{
    // 创建计算器对象
    Calculator c;
    c.m_Num1 = 10;
    c.m_Num2 = 10;

    cout << c.m_Num1 << " + " << c.m_Num2 << " = " << c.getResult("+") << endl;
    cout << c.m_Num1 << " - " << c.m_Num2 << " = " << c.getResult("-") << endl;
    cout << c.m_Num1 << " * " << c.m_Num2 << " = " << c.getResult("*") << endl;
    cout << c.m_Num1 << " / " << c.m_Num2 << " = " << c.getResult("/") << endl;
}

// 利用多态实现计算器

// 实现计算器抽象类
class AbstractCalculator
{
public:
    virtual int getResult()
    {
        return 0;
    }
    int m_Num1;
    int m_Num2;
};

// 加法计算器类
class Add :public AbstractCalculator
{
    virtual int getResult()
    {
        return m_Num1 + m_Num2;
    }
};

// 减法计算器类
class Sub :public AbstractCalculator
{
    virtual int getResult()
    {
        return m_Num1 - m_Num2;
    }
};

// 乘法计算器类
class Mul :public AbstractCalculator
{
    virtual int getResult()
    {
        return m_Num1 * m_Num2;
    }
};

// 除法计算器类
class Div :public AbstractCalculator
{
    virtual int getResult()
    {
        return m_Num1 / m_Num2;
    }
};

void test02()
{
    // 多态使用条件
    // 父类指针或者引用指向子类对象

    // 加法运算
    AbstractCalculator * abc = new Add;
    abc->m_Num1 = 20;
    abc->m_Num2 = 20;

    cout << abc->m_Num1 << " + " << abc->m_Num2 << " = " << abc->getResult() << endl;

    delete abc;

    // 减法运算
    abc = new Sub;
    abc->m_Num1 = 20;
    abc->m_Num2 = 20;

    cout << abc->m_Num1 << " - " << abc->m_Num2 << " = " << abc->getResult() << endl;

    delete abc;

    // 乘法运算
    abc = new Mul;
    abc->m_Num1 = 20;
    abc->m_Num2 = 20;

    cout << abc->m_Num1 << " * " << abc->m_Num2 << " = " << abc->getResult() << endl;

    delete abc;

    // 除法运算
    abc = new Div;
    abc->m_Num1 = 20;
    abc->m_Num2 = 20;

    cout << abc->m_Num1 << " / " << abc->m_Num2 << " = " << abc->getResult() << endl;

    delete abc;

}

int main()
{
    cout << "test01" << endl;
    test01();

    cout << endl;

    cout << "test02" << endl;
    test02();

    return 0;
}

​ 结果如下:

test01
10 + 10 = 20
10 - 10 = 0
10 * 10 = 100
10 / 10 = 1

test02
20 + 20 = 40
20 - 20 = 0
20 * 20 = 400
20 / 20 = 1

Process returned 0 (0x0)   execution time : 0.028 s
Press any key to continue.

4.7.5 多态案例二-制作饮品


例4.7.5 make drinking

#include <iostream>

using namespace std;

// make drinking
class BaseDrinking
{
public:
    virtual ~BaseDrinking()
    {
        // 基类析构函数实现
    }

    // 煮水
    virtual void Boil() = 0;
    // 冲泡
    virtual void Brew() = 0;
    // 倒入杯中
    virtual void PourInCup() = 0;
    // 加入辅料
    virtual void AddSomethings() = 0;

    // 制作饮品
    void MakeDrink()
    {
        Boil();
        Brew();
        PourInCup();
        AddSomethings();
    }
};

// 制作咖啡
class Coffee :public BaseDrinking
{
public:
    // 煮水
    virtual void Boil()
    {
        cout << "煮农夫山泉" << endl;
    }
    // 冲泡
    virtual void Brew()
    {
        cout << "冲泡咖啡" << endl;
    }
    // 倒入杯中
    virtual void PourInCup()
    {
        cout << "倒入咖啡杯中" << endl;
    }
    // 加入辅料
    virtual void AddSomethings()
    {
        cout << "加入糖和牛奶" << endl;
    }
};

// 制作茶
class Tea :public BaseDrinking
{
public:
    // 煮水
    virtual void Boil()
    {
        cout << "煮娃哈哈" << endl;
    }
    // 冲泡
    virtual void Brew()
    {
        cout << "冲泡茶" << endl;
    }
    // 倒入杯中
    virtual void PourInCup()
    {
        cout << "倒入茶杯中" << endl;
    }
    // 加入辅料
    virtual void AddSomethings()
    {
        cout << "加入柠檬" << endl;
    }
};

// 制作函数
void doWork(BaseDrinking * base)
{
    base->MakeDrink();
    delete base; // 释放
}

void test01()
{
    // 制作咖啡
    doWork(new Coffee);

    cout << "---------------------" << endl;

    // 制作茶
    doWork(new Tea);

}
int main()
{
    test01();
    return 0;
}

​ 结果如下:

煮农夫山泉
冲泡咖啡
倒入咖啡杯中
加入糖和牛奶
---------------------
煮娃哈哈
冲泡茶
倒入茶杯中
加入柠檬

Process returned 0 (0x0)   execution time : 0.078 s
Press any key to continue.

4.7.6 多态案例三-电脑组装


例4.7.6 assembly computer

#include <iostream>

using namespace std;

// 组装电脑

// 抽象不同的零件类

// 抽象CPU类
class CPU
{
public:
    virtual ~CPU()
    {

    }
    // 抽象的计算函数
    virtual void calculate() = 0;
};

// 抽象显卡类
class VideoCard
{
public:
    virtual ~VideoCard()
    {

    }
    // 抽象的显示函数
    virtual void display() = 0;
};

// 抽象内存条类
class Memory
{
public:
    virtual ~Memory()
    {

    }
    // 抽象的存储函数
    virtual void storage() = 0;
};

class Computer
{
public:
    Computer(CPU * cpu, VideoCard * vc, Memory *mem)
    {
        m_cpu = cpu;
        m_vc = vc;
        m_mem = mem;
    }
    // 提供工作的函数
    void work()
    {
        // 让零件工作起来,调用接口
        m_cpu->calculate();

        m_vc->display();

        m_mem->storage();
    }
    // 提供析构函数 释放3个电脑零件
    virtual ~Computer()
    {
        // 释放CPU零件
        if (m_cpu != NULL)
        {
            delete m_cpu;
            m_cpu = NULL;
        }
        // 释放显卡零件
        if (m_vc != NULL)
        {
            delete m_vc;
            m_vc = NULL;
        }
        // 释放内存条零件
        if (m_mem != NULL)
        {
            delete m_mem;
            m_mem = NULL;
        }
    }
private:
    CPU * m_cpu; // CPU的零件指针
    VideoCard * m_vc; // 显卡零件指针
    Memory * m_mem; // 内存条零件指针
};

// 具体厂商

// intel厂商
class IntelCPU :public CPU
{
public:
    virtual void calculate()
    {
        cout << "Intel的CPU开始计算了" << endl;
    }
};

class IntelVideoCard :public VideoCard
{
public:
    virtual void display()
    {
        cout << "Intel的显卡开始显示了" << endl;
    }
};

class IntelMemory :public Memory
{
public:
    virtual void storage()
    {
        cout << "Intel的内存条开始存储了" << endl;
    }
};


// AMD厂商
class AMDCPU :public CPU
{
public:
    virtual void calculate()
    {
        cout << "AMD的CPU开始计算了" << endl;
    }
};

class AMDVideoCard :public VideoCard
{
public:
    virtual void display()
    {
        cout << "AMD的显卡开始显示了" << endl;
    }
};

class AMDMemory :public Memory
{
public:
    virtual void storage()
    {
        cout << "AMD的内存条开始存储了" << endl;
    }
};

void test01()
{
    // 第一台电脑零件
    CPU * intelcpu = new IntelCPU;
    VideoCard * intelCard = new IntelVideoCard;
    Memory * intelMem = new IntelMemory;

    cout << "第一台电脑开始工作:" << endl;
    // 创建第一台电脑
    Computer * Computer1 = new Computer(intelcpu, intelCard, intelMem);
    Computer1->work();
    delete Computer1;

    cout << "----------------------" << endl;
    cout << "第二台电脑开始工作:" << endl;
    // 第二台电脑组装
    Computer * Computer2 = new Computer(new AMDCPU, new AMDVideoCard, new AMDMemory);
    Computer2->work();
    delete Computer2;

}
int main()
{
    test01();
    return 0;
}

​ 结果如下:

第一台电脑开始工作:
Intel的CPU开始计算了
Intel的显卡开始显示了
Intel的内存条开始存储了
----------------------
第二台电脑开始工作:
AMD的CPU开始计算了
AMD的显卡开始显示了
AMD的内存条开始存储了

Process returned 0 (0x0)   execution time : 0.072 s
Press any key to continue.

4.7.7 继承与多态案例


​ 题目如下:

​ 上机实验五 继承與多态,请沿用实验三的实验结果, 以公开(public)继承 Person 类产生一个 Student 类(class)。
以及 Teacher 类。注意: Person 类的 print()成员已经设为虚函数(virtual function)。
​ 将类定义(class definition)写在 Person.h, Date.h, Student.h 及 Teacher.h 中。 将成员函数的定义(member function definition)写在person.cpp, Date.cpp, Student.cpp 及Teacher.cpp 中。在主程序中实例化二个 Person对象,二个 Student 对象,一个 Teacher 对象。并在主程序中定义一个 Person 的指针数组,将数组中的指针分别指向上述五个对象。 利用 for 及指针数组调用数组指针指向的每个对象的 print 成员函数顺序打印对象的内容。
Person

-Name : string
-ID : int
-Address : string
-Birthday: Date
<<constructor>> +Person(name : string = “”, id : int = 0,
address : string = “”, Date = Date())
<<desctructor>> +~Person()
+setName(name : string)
+getName() : string
+setID(id : int)
+getID() : int
+setAddress(address : string)
+getAddress() : string
+setBirthday(d : Date)
+getBirthday() : Date
+virtual print() : void

Date

<<constructor>>+Date(y : int = 0,
m : int = 0, d : int = 0)
<<destructor>>+~Date()
+setYear(y : int) : void
+setMonth(m : int) : void
+setDay(d : int) : void
+getYear() : int
+getMonth() : int
+getDay() : int
+print() : void
-Year : int
-Month : int
-Day : int
Student
-Department:string
-studentID:int
<<constructor>> +Student (name:string=””,
id:int=0, address:string=””, Date=Date(),
Dep:string=””, sID:int=0)
<<destructor>> +~Student()
+setDepartment(Dep:string):void
+setStudentID(sID:int):void
+getDepartment():string
+getStudentID():int
+print():void

Teacher

-Department:string
-Salary:double
<<constructor>> +Teacher(name:string,
id:int=0, address:string=””, Date=Date(),
Dep:string=””,sal:double=0.0)
<<destructor>> +~Teacher()
+setDepartment(Dep:string):void
+setSalary(sal:duble):void
+getDepartment():string
+getSalary():double
+print():void

​ 解答如下:

​ main.cpp

#include <iostream>
#include "Person.h"

#include "Student.h"

#include "Teacher.h"
using namespace std;

int main()
{
    Person p1("Alice", 1, "123 Street");
    Person p2("Bob", 2, "456 Avenue");

    Student s1("Charlie", 3, "789 Boulevard", Date(2000, 3, 1), "Math", 1001);
    Student s2("David", 4, "101 Lane", Date(2001, 7, 22), "Physics", 1002);

    Teacher t1("Eve", 5, "202 Road", Date(1975, 1, 1), "Biology", 50000);

    Person* people[] = {&p1, &p2, &s1, &s2, &t1}; // 容器

    for (const auto& person : people) // output
    {
        person->print();
    }

    return 0;
}

​ Person.h

#ifndef PERSON_H

#define PERSON_H
#include <iostream>
#include "Date.h"
using namespace std;

class Person
{
public:
    Person();
    Person(string name, int id, string address);
    ~Person();

    void setPerson(string name, int id, string address);
    void setName(string name);
    void setID(int id);
    void setAddress(string address);
    void setBirthday(Date d);

    string getName();
    int getID();
    string getAddress();
    Date getBirthday();

    virtual void print(); // outPutResult
private:
    string Name;
    int ID;
    string Address;
    Date Birthday;
};
#endif // PERSON_H

​ Student.h

#ifndef STUDENT_H

#define STUDENT_H
#include <iostream>
#include "Person.h"
#include "Date.h"
using namespace std;

class Student :public Person
{
public:
    Student();
    Student(string name, int id, string address, Date date, string department, int studentID);
    ~Student();

    void setDepartment(string department);
    void setStudentID(int studentID);

    string getDepartment();
    int getStudentID();

    virtual void print(); // outPutResult
private:
    string Department;
    int StudentID;
};
#endif // STUDENT_H

​ Teacher.h

#ifndef TEACHER_H

#define TEACHER_H
#include "Person.h"
#include "Date.h"
using namespace std;

class Teacher :public Person
{
public:
    Teacher();
    Teacher(string name, int id, string address, Date date, string department, double salary);
    ~Teacher();

    void setDepartment(string department);
    void setSalary(double salary);

    string getDepartment();
    double getSalary();

    virtual void print(); // outPutResult
private:
    string Department;
    double Salary;
};
#endif // TEACHER_H

​ Person.cpp

#include "Person.h"
#include <iostream>
using namespace std;

Person::Person()
{
    Name = "S.M.Wang";
    ID = 070145;
    Address = "莲花路200号";
}

Person::Person(string name, int id, string address)
{
    setPerson(name, id, address);
}

Person::~Person()
{
    //cout << "object Destructor is called" << endl;
}


void Person::setPerson(string name, int id, string address)
{
    Name = name;
    ID = id;
    Address = address;
}


void Person::setName(string name)
{
    Name = name;
}

void Person::setID(int id)
{
    ID = id;
}

void Person::setAddress(string address)
{
    Address = address;
}

string Person::getName()
{
    return Name;
}

int Person::getID()
{
    return ID;
}

string Person::getAddress()
{
    return Address;
}


void Person::setBirthday(Date d) // 调用的形参是类
{
    Birthday = d;
}

Date Person::getBirthday() // 返回的是类
{
    return Birthday;
}

void Person::print()
{
    cout << "Name:" << getName() << endl;
    cout << "ID:" << getID() << endl;
    cout << "Address:" << getAddress() << endl;

    cout << "Birthday:" << getBirthday().getYear(); // getBirthday()返回的是类,再调用类中的子函数满足cout的返回值。
    cout << " " << getBirthday().getMonth();
    cout << " " << getBirthday().getDay() << endl;
    cout << endl;
}

​ Student.cpp

#include "Student.h"
#include <iostream>
using namespace std;

Student::Student()
{

}

Student::Student(string name, int id, string address, Date date, string department, int studentID)
{
    setPerson(name, id, address);
    setBirthday(date);
    setDepartment(department);
    setStudentID(studentID);
}

Student::~Student()
{
    //cout << "object Destructor is called" << endl;
}

void Student::setDepartment(string department)
{
    Department = department;
}

string Student::getDepartment()
{
    return Department;
}

void Student::setStudentID(int studentID)
{
    StudentID = studentID;
}

int Student::getStudentID()
{
    return StudentID;
}

void Student::print()
{
    cout << "Name:" << getName() << endl;
    cout << "ID:" << getID() << endl;
    cout << "Address:" << getAddress() << endl;

    cout << "Birthday:" << getBirthday().getYear(); // getBirthday()返回的是类,再调用类中的子函数满足cout的返回值。
    cout << " " << getBirthday().getMonth();
    cout << " " << getBirthday().getDay() << endl;

    cout << "Department:" << getDepartment() << endl;
    cout << "StudentID:" << getStudentID() << endl;
    cout << endl;

}

​ Teacher.cpp

#include "Teacher.h"
#include <iostream>
using namespace std;

Teacher::Teacher()
{

}

Teacher::Teacher(string name, int id, string address, Date date, string department, double salary)
{
    setPerson(name, id, address);
    setBirthday(date);
    setDepartment(department);
    setSalary(salary);
}

Teacher::~Teacher()
{
    //cout << "object Destructor is called" << endl;
}

void Teacher::setDepartment(string department)
{
    Department = department;
}

string Teacher::getDepartment()
{
    return Department;
}

void Teacher::setSalary(double salary)
{
    Salary = salary;
}

double Teacher::getSalary()
{
    return Salary;
}

void Teacher::print()
{
    cout << "Name:" << getName() << endl;
    cout << "ID:" << getID() << endl;
    cout << "Address:" << getAddress() << endl;

    cout << "Birthday:" << getBirthday().getYear(); // getBirthday()返回的是类,再调用类中的子函数满足cout的返回值。
    cout << " " << getBirthday().getMonth();
    cout << " " << getBirthday().getDay() << endl;

    cout << "Department:" << getDepartment() << endl;
    cout << "Salary:" << getSalary() << endl;
    cout << endl;
}

​ 结果如下:

Name:Bob
ID:2
Address:456 Avenue
Birthday:0 0 0

Name:Charlie
ID:3
Address:789 Boulevard
Birthday:2000 3 1
Department:Math
StudentID:1001

Name:David
ID:4
Address:101 Lane
Birthday:2001 7 22
Department:Physics
StudentID:1002

Name:Eve
ID:5
Address:202 Road
Birthday:1975 1 1
Department:Biology
Salary:50000


Process returned 0 (0x0)   execution time : 0.011 s
Press any key to continue.

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

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

相关文章

初识git · 远程操作

目录 前言&#xff1a; 理解分布式版本控制系统 远程仓库 仓库操作 克隆仓库 推送和抓取 特殊文件 取别名 标签管理 前言&#xff1a; 在基本操作&#xff0c;分支管理这几个部分&#xff0c;我们都会在本地仓库操作了&#xff0c;但是目前还没有办法将自己的代码远程…

uniapp 实现input聚焦时选中内容(已封装)兼容微信小程序

老规矩先来看看效果噻&#xff01; 从上面的录屏中我们可以看出&#xff0c;要实现input自由选中内容的功能是可以实现的&#xff0c;原理其实很简单。 直接运行即可 <template><view><!-- <input class"psd"type"digit" :value"in…

第二代 GPT-SoVITS V2:解锁语音克隆与合成的无限可能

在 AI 技术蓬勃发展的今天&#xff0c;第二代 GPT-SoVITS V2 如一颗璀璨的明星闪耀登场&#xff0c;为语音处理领域带来了前所未有的变革。它是一款集先进技术与强大功能于一身的声音克隆与语音合成工具&#xff0c;由 RVC 变声器创始人 “花儿不哭” 与 AI 音色转换技术 Sovit…

当小程序学会‘读心术’:表单处理的神秘法则

哈喽&#xff0c;我是阿佑&#xff0c;今天将给大家给咱们的小程序赋能——“读心术”&#xff01; 文章目录 微信小程序的表单处理表单元素&#xff1a;小程序的“语言”表单事件&#xff1a;小程序的“听觉”表单提交&#xff1a;小程序的“表达”总结 微信小程序的表单处理 …

Oracle数据库系统表空间过大,清理SYSTEM、SYSAUX表空间

一.前言 在oracle数据库中&#xff0c;system为系统表空间&#xff0c;存放着一些我们经常用到的系统表和视图&#xff0c;sysaux为辅助表空间&#xff0c;辅助着系统表空间。这两个表空间不宜添加数据文件&#xff0c;会使系统表空间过于臃肿&#xff0c;从而影响数据库的使用…

【Jenkins】2024 最新版本的 Jenkins 权限修改为 root 用户启动,解决 permission-denied 报错问题

最新版本的 Jenkins 修改 /etc/sysconfig/jenkins 中的 JENKINS_USERroot不会再生效&#xff0c;需要按照以下配置进行操作&#xff1a; vim /usr/lib/systemd/system/jenkins.service然后重启就可以了 systemctl daemon-reload # 重新加载 systemd 的配置文件 systemctl res…

Shell编程-案例一(数据库备份服务监测)

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们前面学习了那么多命令&#xff0c;以及涉及到部分逻辑判断的问题。从简单来说&#xff0c;他就是Shell编程&#xff0c;…

基于Multisim三极管B放大系数放大倍数测量电路设计(含仿真和报告)

【全套资料.zip】三极管B放大系数放大倍数测量电路电路设计Multisim仿真设计数字电子技术 文章目录 功能一、Multisim仿真源文件二、原理文档报告资料下载【Multisim仿真报告讲解视频.zip】 功能 1.用三个数码管显示B的大小&#xff0c;分别显示个位、十位和百位。 2.显示范围…

springboot041师生健康信息管理系统(论文+源码)_kaic

摘 要 随着移动应用技术的发展&#xff0c;越来越多的用户借助于移动手机、电脑完成生活中的事务&#xff0c;许多的传统行业也更加重视与互联网的结合。 本论文主要介绍基于java的师生健康信息管理系统&#xff0c;运用软件工程原理和开发方法&#xff0c;采用springboot框架…

C++ 进阶:类相关特性的深入探讨

⭐在对C 中类的6个默认成员函数有了初步了解之后&#xff0c;现在我们进行对类相关特性的深入探讨&#xff01; &#x1f525;&#x1f525;&#x1f525;【C】类的默认成员函数&#xff1a;深入剖析与应用&#xff08;上&#xff09; 【C】类的默认成员函数&#xff1a;深入剖…

【凸优化】Legendre变换、共轭函数、对偶

推荐文章 [凸优化-凸共轭]Legendre and Legendre-Fenchel transforms - 知乎 (zhihu.com) 一、Legendre变换 1、几何解释1 Legendre 变换通过选择斜率 作为新的自变量&#xff0c;将函数描述为它的斜率与相应的 x 的函数值之间的关系。几何上&#xff0c;它可以理解为用函…

Vert.x,认证与授权 - HTTP基本认证

几乎所有的线上系统都离不开认证和授权&#xff0c;Vert.x auth相关组件提供了丰富(Session&#xff0c;JTW, OAuth&#xff0c;…)&#xff0c;便捷的认证和授权支持。 当前&#xff0c;使用最多是Web应用&#xff0c;所以在后续讨论中&#xff0c;都是关于Vert.x auth在Web应…

kernel32.dll下载地址:如何安全地恢复系统文件

关于从网络上寻找kernel32.dll的下载地址&#xff0c;这通常不是一个安全的做法&#xff0c;而且可能涉及到多种风险。kernel32.dll是Windows操作系统的核心组件之一&#xff0c;负责内存管理、进程和线程管理以及其他关键系统功能。因为kernel32.dll是系统的基础文件&#xff…

IDEA如何给debug断点加上筛选条件判断

前言 我们在使用IDEA开发Java应用时&#xff0c;经常是需要进行代码调试的&#xff0c;这就需要打断点进行操作。但有些时候&#xff0c;我们只希望在符合某种条件的情况下&#xff0c;才去到这个断点&#xff0c;不符合的情况下&#xff0c;直接跳过断点&#xff0c;这其实也…

【linux】线程 (三)

13. 常见锁概念 &#xff08;一&#xff09;了解死锁 死锁是指在一组进程中的各个进程均占有不会释放的资源&#xff0c;但因互相申请被其他进程占有的&#xff0c;且不释放的资源&#xff0c;而处于的一种永久等待状态 &#xff08;二&#xff09;死锁四个必要条件 互斥条件…

深度学习(一)基础:神经网络、训练过程与激活函数(1/10)

深度学习基础&#xff1a;神经网络、训练过程与激活函数 引言&#xff1a; 深度学习作为机器学习的一个子领域&#xff0c;近年来在人工智能的发展中扮演了举足轻重的角色。它通过模仿人脑的神经网络结构&#xff0c;使得计算机能够从数据中学习复杂的模式和特征&#xff0c;…

COLA架构生成DDD项目

1.下载代码 https://github.com/alibaba/COLA 2.执行命令 2.1 shell Linux mvn archetype:generate \-DgroupIdcom.xxc \-DartifactIdcola-springboot-demo \-Dversion0.0.1 \-Dpackagecom.xxc.demo \-DarchetypeArtifactIdcola-framework-archetype-web \-DarchetypeGrou…

我是类(最终版)

文章目录 再看构造函数类型转换static静态成员友元内部类匿名对象对象拷贝时的编译器优化 再看构造函数 本标题的目的是解决如下问题&#xff1a;当实现MyQueue时&#xff0c;我们不需要写默认构造函数&#xff0c;因为编译器会调用Stack的默认构造&#xff0c;但是&#xff0…

01 设计模式-创造型模式-工厂模式

工厂模式&#xff08;Factory Pattern&#xff09;是 Java 中最常用的设计模式之一&#xff0c;它提供了一种创建对象的方式&#xff0c;使得创建对象的过程与使用对象的过程分离。 工厂模式提供了一种创建对象的方式&#xff0c;而无需指定要创建的具体类。 通过使用工厂模式…

vue 页面导出gif图片 img 导出gif 超简单~

1.首先需要新建一个文件件 新建gif文件夹。这两个文件在文章最后面需要可自提 2.出gif分为两种情况 第一种情况 页面是img标签&#xff0c;直接导出图片作为gif 第二种情况 页面是div标签&#xff0c;需要导出div里面的图片作为gif 2.1页面是img标签&#xff0c;直接导出图…