C++基础一文通(四)面向对象

一. 面向对象

1. 创建类

语法: class 类名{ 访问权限: 属性 / 行为 };

例如: 创建学生类

#include <iostream>
using namespace std;

//学生类
class Student
{
public:
    void setName(string name)
    {
        m_name = name;
    }
    void setID(int id)
    {
        m_id = id;
    }

    void showStudent()
    {
        cout << "name:" << m_name << " ID:" << m_id << endl;
    }

public:
    string m_name;
    int m_id;
};

int main()
{

    Student stu; // 实例化

    stu.m_name = "ddd";
    stu.m_id = 123;
    // 操作属性
    cout << "stu.m_name : " << stu.m_name << endl;
    cout << "stu.m_id : " << stu.m_id << endl;

    // 使用方法
    stu.setName("anny");
    stu.setID(7);
    stu.showStudent();

    return 0;
}

2. 类的权限

类在设计时,可以把属性和行为放在不同的权限下,加以控制

访问权限有三种:

  • public 公共权限 (类内可以访问 类外可以访问)
  • protected 保护权限 (类内可以访问 类外不可以访问, 子类可以访问)
  • private 私有权限 (类内可以访问 类外不可以访问, 子类不可以访问, 这是类默认的!!!!)

对于不能访问的属性和方法, 只能通过暴露接口来访问
类的默认权限是private!!!!!!!!

3. 在C++中 struct和class唯一的区别就在于 默认的访问权限不同

struct 默认权限为公共
struct Student
{
    string m_name;
    void set_id(int a)
    {
        m_id = a;
    }
    void show_id()
    {
        cout << m_id << endl;
    }
//struct默认public, 如果需要private, 则需要声明
private:
    int m_id;
};

int main()
{

    Student stu;
    stu.m_name = "ddd";
    stu.set_id(123);
    // 操作属性
    cout << "stu.m_name : " << stu.m_name << endl;
    stu.show_id();
    return 0;
}
class 默认权限为私有
#include <iostream>
using namespace std;

class Student
{
    int m_id;

public:
    string m_name;
    void set_id(int a)
    {
        m_id = a;
    }
    void show_id()
    {
        cout << m_id << endl;
    }
};

int main()
{

    Student stu;
    stu.m_name = "ddd";
    stu.set_id(123);
    // 操作属性
    cout << "stu.m_name : " << stu.m_name << endl;
    stu.show_id();
    return 0;
}

4. 成员属性设置为私有是很不错的做法!

成员属性设置为私有是很不错的做法!

优点1:将所有成员属性设置为私有,可以自己控制读写权限
优点2:对于写权限,我们可以检测数据的有效性

二. 构造函数

c++利用了构造函数析构函数解决对象实例化问题,这两个函数将会被编译器自动调用,完成对象初始化和清理工作。

  • 构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。
  • 析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作。

1. 构造函数

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

  1. 构造函数,没有返回值也不写void
  2. 函数名称与类名相同
  3. 构造函数可以有参数,因此可以发生重载
#include <iostream>
using namespace std;

class Student
{
public:
    Student(string name,int id)
    {
        m_name = name;
        m_id = id;
    }
    void show_info()
    {
        cout<< m_name <<endl;
        cout<< m_id <<endl;
    }
private:
    string m_name;
    int m_id;
};

int main()
{

    Student stu("anny",7);
    stu.show_info();

    Student stu2("haha",18);
    stu.show_info();
    stu2.show_info();
    return 0;
}
  

2. 构造函数分类

两种分类方式:

按参数分为: 有参构造和无参构造
按类型分为: 普通构造和拷贝构造

三种调用方式:

  • 括号法 Person p1(10);
  • 显示法 Person p2 = Person(10);
  • 隐式转换法 Person p4 = 10;

注意:调用无参构造函数不能加括号,如果加了编译器认为这是一个函数声明

#include <iostream>
using namespace std;

class Person
{
public:
    //无参(默认)构造函数
    Person()
    {
        cout << "无参构造函数!" << endl;
    }
    //有参构造函数
    Person(int a)
    {
        age = a;
        cout << "有参构造函数!" << endl;
    }

public:
    int age;
};

int main()
{
    // 1 调用无参构造函数
    Person p; //调用无参构造函数

    // 2.1  括号法,常用
    Person p1(10);
    //注意:调用无参构造函数不能加括号,如果加了编译器认为这是一个函数声明
    // Person p2();××××错!!!!!!!!!××××

    // 2.2 显式法
    Person p2 = Person(10);

    // 2.3 隐式转换法
    Person p4 = 10; 

    return 0;
}

3. 拷贝构造函数

拷贝构造函数就是用一个实例来构造另一个实例, 是一门克隆技术

注意: 拷贝构造函数要使用常量引用
如果不写拷贝构造函数, C++也会自动生成一个拷贝构造函数, 调用时会直接克隆, 而且是浅拷贝!!!

#include <iostream>
using namespace std;

class Person
{
public:
    //有参构造函数
    Person(int a)
    {
        age = a;
    }
    Person(const Person &a_person)
    {
        age = a_person.age + 10;
        cout << "拷贝构造函数!" << endl;
        cout << "克隆人的诞生!" << endl;
    }

public:
    int age;
};

int main()
{

    Person p1(10);

    Person p2 = Person(p1);
    cout << p2.age << endl;
    return 0;
}

4. 解决拷贝构造函数的"浅拷贝"问题必须收到创建拷贝构造函数

三. 构造函数的简写

C++提供了初始化语法,来用形参初始化属性
语法:Person(int a, int b, int c) : m_A(a), m_B(b), m_C(c) {}

#include <iostream>
using namespace std;

class Person
{
public:
    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 p1(10, 20, 30);
    p1.PrintPerson();
    return 0;
}

四. 析构函数

  • 程序在实例化对象时候会自动调用构造,无须手动调用,而且只会调用一次
#include <iostream>
using namespace std;

class Student
{
public:
    Student(string name,int id)
    {
        m_name = name;
        m_id = id;
    }
    ~Student()
    {
        cout << "析构函数执行!"<<endl;
    }
    void show_info()
    {
        cout<< m_name <<endl;
        cout<< m_id <<endl;
    }
private:
    string m_name;
    int m_id;
};

int main()
{
    Student stu("anny",7);
    stu.show_info();
}

五. 类属性和类方法

1. 静态成员(类属性)

静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员

2. 类属性

  • 静态成员参数
    • 所有对象共享同一份数据
    • 在编译阶段分配内存
    • 类内声明,类外初始化

注意: 类属性要 : 类内声明,类外初始化

#include <iostream>
using namespace std;

class Person
{
public:
    static int m_A;
    void show_a()
    {
        cout << m_A << endl;
    }
};
// 必须在外面初始化变量
int Person::m_A = 10;
int main()
{
    Person p1;
    p1.m_A = 100;
    p1.show_a();

    Person p2;
    p2.show_a();
    return 0;
}

3. 类方法

静态成员函数

  • 所有对象共享同一个函数
  • 静态成员函数只能访问静态成员变量

注意: 静态成员函数只能访问静态成员变量

#include <iostream>
using namespace std;

class Person
{
public:
    static int m_A;
    static void show_a()
    {
        cout << m_A << endl;
    }
};
// 必须在外面初始化变量
int Person::m_A = 10;
int main()
{
    Person p1;
    p1.m_A = 100;
    p1.show_a();

    Person p2;
    p2.show_a();
    return 0;
}

非静态的属性和方法就是 : 实例属性/实例方法

六. C++ this指针

this指针 是 c++通过提供特殊的对象指针, this指针指向被调用的成员函数所属的对象

七. 常对象及常函数

常函数可以认为只读函数
常对象可以认为只有读权限的对象

1. 常函数 (创建类时, 可以在类中创建常函数)

  • 成员函数后加const后我们称为这个函数为常函数
  • 常函数内不可以修改成员属性
  • 成员属性声明时加关键字mutable后,在常函数中依然可以修改
#include <iostream>
using namespace std;

class Person
{
public:
    int m_A;
    void show_a() const
    {
        cout << "常函数执行," << m_A << endl;
    }
};

int main()
{
    Person p1;
    p1.show_a();
}

2. 常对象 (实例化类时, 可以实例化常对象)

#include <iostream>
using namespace std;

class Person
{
public:
    Person()
    {
        m_A = 0;
    }
    void show_a() const
    {
        cout << "常函数执行," << m_A << endl;
    }

public:
    int m_A;
};

int main()
{
    const Person p1;
    p1.show_a();
}

3. 常对象只能调用常函数和静态函数, 无法调用成员函数

  • 常对象可以调用类属性, 也能修改它们
  • 常对象只能调用实例属性, 但不能修改它们
  • 常对象只能调用常函数和类方法, 无法调用实例方法
#include <iostream>
using namespace std;

class Person
{
public:
    Person(int a)
    {
        this->m_A = a; // 成员属性(实例属性)
    }
    void show_a() const // 常函数
    {
        cout << "常函数执行," << m_A << endl;
    }

    static void show_b() //静态方法(类方法)
    {
        cout << "静态函数执行," << m_B << endl;
    }
    void show_c() // 实例方法
    {
        cout << "成员函数执行," << m_A << endl;
    }

public:
    int m_A;
    static int m_B; // 静态参数 (类属性)
};
int Person::m_B = 200; //静态参数赋值 (类属性赋值)
int main()
{
    const Person p1 = Person(100);
    // p1.m_A = 200;  常对象无法修改实例属性
    cout << p1.m_A << endl; //常对象可以访问实例属性
    p1.m_B = 300;           //常对象可以修改类属性
    cout << p1.m_B << endl; //常对象可以访问类属性
    p1.show_a();            //常对象可以调用常函数
    p1.show_b();            //常对象可以调用类方法
    // p1.show_c(); //常对象无法调用成员方法(实例方法)
}

八. 运算符重载 (魔法)

1. 以 + 的重载为例

#include <iostream>
using namespace std;

class Person
{
public:
    Person(){};
    Person(int a, int b)
    {
        this->m_A = a;
        this->m_B = b;
    }
    //成员函数实现 + 号运算符重载
    Person operator+(const Person &p)
    {
        Person temp;
        temp.m_A = this->m_A + p.m_A;
        temp.m_B = this->m_B + p.m_B;
        return temp;
    }

public:
    int m_A;
    int m_B;
};
int main()
{
    Person p1(3, 4);

    Person p2(7, 8);

    Person p3 = p1 + p2;

    cout << p3.m_A << endl;
    cout << p3.m_B << endl;
}

值得一提的时, 操作符方法是可以根据不同的传参进行重载的

2. C++ 可操作的运算符重载

下面是可重载的运算符列表:

使用方法参考:

C++运算符重载 https://blog.csdn.net/bzxb355/article/details/124114746

九. 继承

1. 继承的基本语法

//公共页面
class BasePage
{
public:
    void header()
    {
        cout << "首页、公开课、登录、注册...(公共头部)" << endl;
    }

    void footer()
    {
        cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
    }
    void left()
    {
        cout << "Java,Python,C++...(公共分类列表)" << endl;
    }

};

//Java页面
class Java : public BasePage
{
public:
    void content()
    {
        cout << "JAVA学科视频" << endl;
    }
};
//Python页面
class Python : public BasePage
{
public:
    void content()
    {
        cout << "Python学科视频" << endl;
    }
};
//C++页面
class CPP : public BasePage
{
public:
    void content()
    {
        cout << "C++学科视频" << endl;
    }
};

void test01()
{
    //Java页面
    cout << "Java下载视频页面如下: " << endl;
    Java ja;
    ja.header();
    ja.footer();
    ja.left();
    ja.content();
    cout << "--------------------" << endl;

    //Python页面
    cout << "Python下载视频页面如下: " << endl;
    Python py;
    py.header();
    py.footer();
    py.left();
    py.content();
    cout << "--------------------" << endl;

    //C++页面
    cout << "C++下载视频页面如下: " << endl;
    CPP cp;
    cp.header();
    cp.footer();
    cp.left();
    cp.content();


}

int main() {

    test01();

    system("pause");

    return 0;
}

2. 继承的权限

  • public : 可以被子类访问
  • protected : 可以被子类访问
  • private : 只能被本类访问,不能被子类访问;

3. 三种继承方式

4. 公有继承

公有继承的特点:

  • 子类继承父类后, 不会修改
    public 成员,protected 成员,private 成员的访问属性在派生类中不变,
    继续是:public, protected, private
  • 子类的子类继承时还能按照这些权限往下继承
#include <iostream>
using namespace std;

class Base1
{
public:
    int m_A = 666;

protected:
    int m_B = 888;

private:
    int m_C = 999;
};

//公共继承
class Son1 : public Base1
{
public:
    void func()
    {
        cout << "Son m_A : " << m_A << endl; //可访问 public权限
        cout << "Son m_B : " << m_B << endl; //可访问 protected权限
        // cout << "m_C" << m_C << endl; // m_C; //不可访问
    }
};

int main()
{
    Son1 s1;
    s1.func();

    return 0;
}

5. 保护继承

保护继承的特点:

  • 子类继承父类后, 会修改
    public 成员,protected 成员,private 成员的访问属性权限变为:protected, protected, private
  • 因为把父类的public 修改为了protected, 所以无法再外部访问了
  • 子类的子类还会继承这些protected属性, 还是只能内部访问, 无法外部访问
#include <iostream>
using namespace std;

class Base2
{
public:
    int m_A = 666;

protected:
    int m_B = 888;

private:
    int m_C = 999;
};

//保护继承
class Son2 : protected Base2
{
public:
    void func()
    {
        cout << "Son m_A : " << m_A << endl; //可访问 protected权限
        cout << "Son m_B : " << m_B << endl; //可访问 protected权限
        // cout << "m_C" << m_C << endl; // m_C; //不可访问
    }
};

class GrandSon : Son2
{
public:
    void func()
    {
        cout << "GrandSon m_A : " << m_A << endl; //可访问 protected权限
        cout << "GrandSon m_B : " << m_B << endl; //可访问 protected权限
        // cout << "m_C" << m_C << endl; // m_C; //不可访问
    }
};

int main()
{
    Son2 s2;
    s2.func();
    // cout << s2.m_A << endl; // 不可访问,因为m_A已经是protect权限了
    GrandSon ss2;
    ss2.func();
    // cout << ss2.m_A << endl; // 不可访问,因为m_A已经是protect权限了
    return 0;
}

6. 私有继承

保护继承的特点:

  • 子类继承父类后, 会修改
    public 成员,protected 成员,private 成员的访问属性权限变为:private, private, private
  • 因为把父类的public 修改为了private, 所以无法再外部访问了, 而且无法再继承下去
  • 子类的子类不会继承这些private属性了, 无法访问
#include <iostream>
using namespace std;

class Base3
{
public:
    int m_A = 666;

protected:
    int m_B = 888;

private:
    int m_C = 999;
};

//私有继承
class Son3 : private Base3
{
public:
    void func()
    {
        cout << "Son m_A : " << m_A << endl; //可访问 private权限
        cout << "Son m_B : " << m_B << endl; //可访问 private权限
        // cout << "m_C" << m_C << endl; // m_C; //不可访问
    }
};

class GrandSon : Son3
{
public:
    void func()
    {
        // Son3是私有继承,所以继承Son3的属性在GrandSon中都无法访问到
    }
};

int main()
{
    Son3 s3;
    s3.func();
    // cout << s2.m_A << endl; // 不可访问,因为m_A已经是private权限了
    GrandSon ss3;
    ss3.func();
    // cout << ss2.m_A << endl; // 不可访问,因为根本没继承
    return 0;
}

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

7. 子类新建属性和父类重名问题

当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据呢?

  • 访问子类同名成员 直接访问即可
  • 访问父类同名成员 需要加作用域
#include <iostream>
using namespace std;

class Base
{
public:
    Base()
    {
        m_A = 100;
    }

    void func()
    {
        cout << "Base - func()调用" << endl;
    }

    void func(int a)
    {
        cout << "Base - func(int a)调用" << endl;
    }

public:
    int m_A;
};

class Son : public Base
{
public:
    Son()
    {
        m_A = 200;
    }

    //当子类与父类拥有同名的成员函数,子类会隐藏父类中所有版本的同名成员函数
    //如果想访问父类中被隐藏的同名成员函数,需要加父类的作用域
    void func()
    {
        cout << "Son - func()调用" << endl;
    }

public:
    int m_A;
};

int main()
{

    Son s;

    cout << "Son下的m_A = " << s.m_A << endl;
    cout << "Base下的m_A = " << s.Base::m_A << endl;

    s.func();
    s.Base::func();
    s.Base::func(10);

    return EXIT_SUCCESS;
}

十. 多态

  • 假设: 猫猫、狗狗都继承Animal 类型
  • 编写一个函数DoSpeak, 传入泛Animal 类型, 传入猫就是猫叫, 传入狗就是狗叫
class Animal
{
public:
    //Speak函数就是虚函数
    //函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。
    virtual void speak()
    {
        cout << "动物在说话" << endl;
    }
};

class Cat :public Animal
{
public:
    void speak()
    {
        cout << "小猫在说话" << endl;
    }
};

class Dog :public Animal
{
public:

    void speak()
    {
        cout << "小狗在说话" << endl;
    }

};
// 编写一个函数, 传入泛Animal 类型, 传入猫就是猫叫, 传入狗就是狗叫
void DoSpeak(Animal & animal)
{
    animal.speak();
}

int main() {

    Cat cat;
    DoSpeak(cat);


    Dog dog;
    DoSpeak(dog);
    return 0;
}

例: 用多态的风格编写计算器

C++开发提倡利用多态设计程序架构,因为多态优点很多

//多态实现
//抽象计算器类
//多态优点:代码组织结构清晰,可读性强,利于前期和后期的扩展以及维护
class AbstractCalculator
{
public :

    virtual int getResult()
    {
        return 0;
    }

    int m_Num1;
    int m_Num2;
};

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

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

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


void test02()
{
    //创建加法计算器
    AbstractCalculator *abc = new AddCalculator;
    abc->m_Num1 = 10;
    abc->m_Num2 = 10;
    cout << abc->m_Num1 << " + " << abc->m_Num2 << " = " << abc->getResult() << endl;
    delete abc;  //用完了记得销毁

    //创建减法计算器
    abc = new SubCalculator;
    abc->m_Num1 = 10;
    abc->m_Num2 = 10;
    cout << abc->m_Num1 << " - " << abc->m_Num2 << " = " << abc->getResult() << endl;
    delete abc;  

    //创建乘法计算器
    abc = new MulCalculator;
    abc->m_Num1 = 10;
    abc->m_Num2 = 10;
    cout << abc->m_Num1 << " * " << abc->m_Num2 << " = " << abc->getResult() << endl;
    delete abc;
}

int main() {

    //test01();

    test02();

    system("pause");

    return 0;
}

十一. 纯虚函数和抽象类

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

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

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

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

抽象类特点

  • 无法实例化对象
  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类
#include <iostream>
using namespace std;

class Toy
{
public:
    virtual void show_price() = 0;
    virtual float raise_price(float) = 0;
    virtual void change_name(string) = 0;
    virtual void open() = 0;
    virtual void play() = 0;
    void first_play()
    {
        open();
        play();
    }
};

class LegoToy : public Toy
{
public:
    LegoToy(string name, float price) : m_name(name), m_price(price){};
    void show_price()
    {
        cout << m_price << endl;
    }
    float raise_price(float raise)
    {
        m_price += raise;
        return m_price;
    }
    void change_name(string newname)
    {
        m_name = newname;
    }
    void open()
    {
        cout << "打开玩具 : " << m_name << endl;
    }

    void play()
    {
        cout << "开始玩价值" << m_price << "元的" << m_name << endl;
    }

public:
    float m_price = 0.0;
    string m_name = "未知";
};
class LiuliuqiuToy : public Toy
{
public:
    LiuliuqiuToy(string name, float price) : m_name(name), m_price(price){};
    void show_price()
    {
        cout << m_price << endl;
    }
    float raise_price(float raise)
    {
        cout << "溜溜球不允许涨价" << endl;
        return m_price;
    }
    void change_name(string newname)
    {
        m_name = newname;
    }
    void open()
    {
        cout << "撕开 " << m_name << "的塑料包装!" << endl;
    }

    void play()
    {
        cout << "旋转跳跃我闭着眼~~~" << endl;
    }

public:
    float m_price = 0.0;
    string m_name = "未知";
};
//业务函数
void play_toy(Toy &toy)
{
    toy.first_play();
}
int main()
{
    LegoToy myLego = LegoToy("乐高打字机", 900);
    play_toy(myLego);
    LiuliuqiuToy myllq("五彩LED溜溜球",3);
    play_toy(myllq);
    return EXIT_SUCCESS;
}

例: 用虚构类 + 多态, 可以实现面向对象的抽象化

下面的例子中, 我们抽象化了制作饮品的过程,

当我们创建子类时, 实现了这些过程, 并完成了制作饮品的过程

//抽象制作饮品
class AbstractDrinking {
public:
    //烧水
    virtual void Boil() = 0;
    //冲泡
    virtual void Brew() = 0;
    //倒入杯中
    virtual void PourInCup() = 0;
    //加入辅料
    virtual void PutSomething() = 0;
    //规定流程
    void MakeDrink() {
        Boil();
        Brew();
        PourInCup();
        PutSomething();
    }
};

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

//制作茶水
class Tea : public AbstractDrinking {
public:
    //烧水
    virtual void Boil() {
        cout << "煮自来水!" << endl;
    }
    //冲泡
    virtual void Brew() {
        cout << "冲泡茶叶!" << endl;
    }
    //倒入杯中
    virtual void PourInCup() {
        cout << "将茶水倒入杯中!" << endl;
    }
    //加入辅料
    virtual void PutSomething() {
        cout << "加入枸杞!" << endl;
    }
};

//业务函数
void DoWork(AbstractDrinking* drink) {
    drink->MakeDrink();
    delete drink;
}

void test01() {
    DoWork(new Coffee);
    cout << "--------------" << endl;
    DoWork(new Tea);
}


int main() {

    test01();

    system("pause");

    return 0;
}

例2: 使用用虚构类虚构元器件 , 组装具体设备时具体实现

#include<iostream>
using namespace std;

//抽象CPU类
class CPU
{
public:
    //抽象的计算函数
    virtual void calculate() = 0;
};

//抽象显卡类
class VideoCard
{
public:
    //抽象的显示函数
    virtual void display() = 0;
};

//抽象内存条类
class Memory
{
public:
    //抽象的存储函数
    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个电脑零件
    ~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 LenovoCPU, new LenovoVideoCard, new LenovoMemory);;
    computer2->work();
    delete computer2;

    cout << "-----------------------" << endl;
    cout << "第三台电脑开始工作:" << endl;
    //第三台电脑组装
    Computer * computer3 = new Computer(new LenovoCPU, new IntelVideoCard, new LenovoMemory);;
    computer3->work();
    delete computer3;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容