c++面向对象三大特性:封装、继承、多态
4.1 封装
将属性和行为作为一个整体
加以权限限制
访问权限
- 公共权限 public 类内可访问,类外可以访问
- 保护权限 protected 类内可访问,类外不可访问 儿子可以访问
父亲保护内容
- 私有权限 private 类内可访问,类外不可访问
儿子不可以访问父亲私有内容
4.1.1 pstruct 和 class 区别
struct默认权限为public
class默认权限为private
4.1.2 成员属性设置为私有
优点:
将所有成员属性设置为私有,可以自己控制读写权限
对于写权限,可以检测数据的有效性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <iostream> using namespace std; class Person { public: void setName(string name1) { name = name1; } string getName() { return name; } int getAge() { return age; } void setLover(string lover1) { lover = lover1; } private: string name; int age; string lover; }; int main() { Person p; p.setName("zhangsan"); cout << p.getName() << endl; cout << "Hello World!\n"; }
|
4.2 对象的初始化和清理
4.2.1 构造函数和析构函数
构造函数:创建对象时为对象的成员属性赋值,无须手动调用
- 类名(){}
- 无返回值,不写void
- 可以有重载
- 程序在调用对象时会自动调用构造函数,
析构函数:对象销毁前系统自动调用,执行清理工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream> using namespace std; class Person { public: Person() { cout << "hello" << endl; } ~Person() { cout << "析构" << endl; } }; int main() { Person p1;//局部变量 栈上的数据,执行完毕后,释放这个对象 }
|
4.2.2 构造函数的分类和使用
有参构造和无参构造(默认构造)
普通构造和拷贝构造
调用方式:括号法、显示法、隐式转换法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| #include <iostream> using namespace std;
class Person { public: Person() { age = 10; cout << "默认构造函数" << endl; }
Person(int a) { age = a; cout << "有参构造函数" << endl; }
Person(const Person &p) { age = p.age; cout << "拷贝构造函数" << endl; }
~Person() { cout << "析构函数" << endl; } public: int age; };
void test() { Person p1(10); Person p2(p1); Person p3; Person p4 = Person(10); Person p5 = Person(p3); Person p6 = 10; Person p7 = p6; } int main() { test(); }
|
4.2.3 拷贝构造函数调用时机
- 使用一个已经创建完毕的对象来初始化一个新对象
- 值传递的方式给函数参数传值
- 以值方式返回局部对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| #include <iostream> using namespace std;
class Person { public: Person() { cout << "默认构造" << endl; } Person(int age) { p_age = age; cout << "有参构造" << endl;
} Person(const Person& p) { p_age = p.p_age; cout << "拷贝构造" << endl;
}
~Person() { cout << "析构" << endl; } private: int p_age; };
void test() { Person p1(20); Person p2(p1); }
void doWork(Person p1) { }
void test2() { Person p; doWork(p); }
Person doWork2() { Person p1; cout << (int*)&p1 << endl; return p1; }
void test3() { Person p = doWork2(); cout << (int*)&p << endl;
} int main() { test3(); }
|
4.2.4 构造函数调用规则
默认情况下,一个类添加3个函数
默认构造、析构、拷贝构造函数
- 如果用户定义有参构造函数,c++不再提供默认无参构造,但是有默认有参构造
- 如果用户定义有参构造函数,c++不再提供默认无参构造,但是有默认有参构造
4.2.5 深拷贝和浅拷贝
浅拷贝:简单的赋值拷贝操作,编译器的默认拷贝构造
问题:堆区内存重复释放
深拷贝:在堆区重新申请空间,进行拷贝操作
如果属性有在堆区开辟的,一定要自己提供拷贝函数,防止浅拷贝带来的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include <iostream> using namespace std;
class Person { public: Person() { cout << "默认构造" << endl; } Person(int age, int heitht) { p_age = age; p_height = new int(heitht); cout << "有参构造" << endl;
} Person(const Person& p) { p_age = p.p_age; cout << "拷贝构造" << endl; p_height = new int(*p.p_height); }
~Person() { if (p_height != NULL) { delete p_height; p_height = NULL; } cout << "析构" << endl; }
int p_age; int* p_height; };
void test() { Person p1(18,180); Person p2(p1);
}
int main() { test(); }
|
4.2.6 初始化列表
初始化属性
构造函数(): 属性1(值1),...{}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <iostream> using namespace std;
class Person { public: Person(int a, int b, int c):a(a),b(b),c(c) { cout << "默认构造" << endl; } ~Person() { cout << "析构" << endl; }
int a; int b; int c;
};
void test() { Person p(30, 20, 10);
}
int main() { test(); }
|
4.2.7 类对象作为类成员
对象成员
当其他类对象作为本类成员,构造时先构造类对象,再构造自身,析构反着来
4.2.8 静态成员
成员前加static
静态成员变量:
- 所有对象共享同一份数据
- 再编译阶段分配内存
- 类内声明,类外初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <iostream> using namespace std;
class Person { public: Person() { cout << "默认构造" << endl; } ~Person() { cout << "析构" << endl; }
static int age; }; int Person::age = 100; void test() { Person p1; Person p2;
} void test2() { Person p; cout << p.age << endl; cout << Person::age << endl; }
int main() { test2();
}
|
静态成员函数
所有对象共享同一个函数
静态成员你函数只能访问静态成员变量
也有访问权限,类外调用不到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <iostream> using namespace std;
class Person { public: static void func() { age = 50; cout << "static" << endl; }
static int age; }; int Person::age = 100;
void test3() { Person p; p.func(); Person::func(); } int main() { test3(); }
|
4.3 c++对象模型和this指针
4.3.1
成员变量和成员函数分开存储
在c++中,类内的成员变量和成员函数分开存储
只有非静态成员变量才属于类的对象上
空对象占用内存空间为1
c++编译器会给每个空对象也分配一个字节空间,是为了区分对象占内存的位置,每个空对象也应该有一个独一无二的内存地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| lass Person {
}; void test() { Person p; cout << sizeof(p) << endl; } int main() { test(); } #include <iostream> using namespace std;
class Person { int m_a; static int b; }; int Person::b = 0; void test1() { Person p; cout << sizeof(p) << endl; } int main() { test1(); }
|
4.3.2 this指针概念
this指针指向被调用的成员函数所属的对象
this指针是隐含每一个非静态成员函数内的一种指针
this指针不需要定义,直接使用即可
this指针的用途:
- 当形参和成员变量同名时,可用this指针来区分
- 在类的非静态成员函数中返回对象本身,可使用return *this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <iostream>
using namespace std;
class Person { public: Person(int age) { this->age = age; } Person& PersonAddAge(Person &p) { this->age += p.age; return *this; } int age; }; int main() { Person p1(10); cout << p1.age << endl; Person p2(10); p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1); cout << p2.age << endl; }
|
4.3.3 空指针访问成员函数
c++中空指针也是可以调用成员函数的,但是要注意有咩有用到this指针
如果用到this指针,需要加以判断保证代码的鲁棒性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <iostream>
using namespace std;
class Person { public: void ShowClassName() { cout << "Person" << endl; } void showAge() { if (this == NULL) { return; } cout << age << endl; } int age; }; void test() { Person* p = NULL; p->ShowClassName(); p->showAge(); } int main() { test(); }
|
4.3.4 const修饰成员函数
常函数:
- 不可以修改成员属性
- 成员属性声明时加关键字mutable后,在常函数、常对象中依然可以修改
常对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include <iostream>
using namespace std;
class Person { public: void ShowPerson() const { b = 100; } int age; mutable int b; }; void test() { Person p; p.ShowPerson(); const Person p1; p1.ShowPerson(); } int main() { test(); }
|
4.4 友元
在程序里,有些私有属性也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术
友元的目的就是让—个函数或者类访问另—个类中私有成员
友元的关键字为friend
友元的三种实现
4.4.1 全局函数做友元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <iostream> using namespace std; class Building { friend void GoodGuy(Building* building); public: Building() { livingRoom = "客厅"; bedroom = "卧室"; } string livingRoom;
private: string bedroom; };
void GoodGuy(Building* building) { cout << "好基友全局函数: " << building->livingRoom << endl; cout << "好基友全局函数: " << building->bedroom << endl;
}
void test() { Building building; GoodGuy(&building); } int main() { test(); }
|
4.4.2 类做友元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include <iostream> using namespace std; class Building;
class GoodGuy { public: GoodGuy(); void Visit(); Building* building;
};
class Building { friend class GoodGuy; public: Building(); string sittingRoom;
private: string bedroom;
};
Building::Building() { sittingRoom = "客厅"; bedroom = "卧室"; }
GoodGuy::GoodGuy() { building = new Building();
}
void GoodGuy::Visit() { cout << "访问:" << building->sittingRoom << endl; cout << "访问:" << building->bedroom << endl; } int main() { GoodGuy gg; gg.Visit(); }
|
4.4.3 成员函数做友元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Building;
class GoodGuy { public: GoodGuy(); void Visit(); Building* building;
};
class Building { friend void GoodGuy::Visit(); public: Building(); string sittingRoom;
private: string bedroom;
};
|
4.5 运算符重载
4.5.1 加号运算符重载
实现两个自定义数据类型相加的运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <iostream>
using namespace std;
class Person { public: Person(int c = 0, int d = 0) :a(c), b(d) {}
int a; int b;
};
Person operator+(Person& p1, Person& p2) { Person temp; temp.a = p1.a + p2.a; temp.b = p1.b + p2.b; return temp; }
int main() { Person p1(10, 10); Person p2(5, 10); Person p3 = p1 + p2; cout << p3.a << endl; cout << p3.b << endl; }
|
4.5.2 左移运算符重载
只能用全局函数重载左移,
配合友元使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <iostream>
using namespace std;
class Person { friend ostream& operator<<(ostream& cout, Person& p); public: Person(int c = 0, int d = 0) :a(c), b(d) {}
private: int a; int b;
};
ostream& operator<<(ostream &cout, Person& p) { cout << p.a << endl; return cout; }
int main() { Person p1(10, 10); Person p2(5, 10); cout << p1 << endl; }
|
4.5.3 递增运算符重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include <iostream>
using namespace std;
class Person {
public: Person(int c = 0, int d = 0) :a(c), b(d) {}
Person& operator++() { a++; return *this; } Person operator++(int) { Person p = *this; a++; return p; } int a; int b;
};
int main() { Person p1(10, 10); int a = (++p1).a; cout << a << endl; }
|
4.5.4 赋值运算符重载
C++编泽器至少给一个类添加4个函数
1.默认构造(函数无参,函数体为空)
2.默认析构(函数无参,函数体为空)
3.默认拷贝构造函数,对属性进行值拷贝
4.赋值运算符operator=,对属性进行值拷贝
如果类中有属性指向堆区,做嘱值操作时也会出现深浅烤贝问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #include <iostream>
using namespace std;
class Person {
public: Person(int l_age) { age = new int(l_age); } ~Person() { if (age != NULL) { delete age; age = NULL; } } Person& operator=(Person &p) { if (age != NULL) { delete age; age = NULL ; } age = new int(*p.age); return *this; } int* age;
};
int main() { Person p1(18); Person p2(20); Person p3(30); p1 = p2 = p3; cout << *p1.age << endl; }
|
4.5.5 关系运算符重载
作用:重载关系运算符,可以让两个自定义类型对象进行对比操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <iostream>
using namespace std;
class Person {
public: Person(string l_name, int l_age) { age = (l_age); name = l_name; } bool operator==(Person& p) { if (name == p.name && age == p.age) { return true; } return false; } bool operator!=(Person& p) { if (name == p.name && age == p.age) { return false; } return true; } string name; int age; };
int main() { Person p1("zhangsan", 18); Person p2("zhangsan", 19); if (p1 == p2) { cout << "相等" << endl; } else { cout << "不相等" << endl; } }
|
4.5.6 函数调用运算符重载 仿函数
函数调用运算符()也可以重载
由于重载后使用的方式非常像函数的调用,因此称为仿函数
仿函数没有固定写法,非常灵活
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <iostream>
using namespace std;
class Person {
public: Person(string l_name, int l_age) { age = (l_age); name = l_name; } void operator()(string test) { cout << test << endl; } string name; int age; };
class myAdd { public: int operator()(int num1, int num2) { return num1 + num2; } }; int main() { Person p1("zhangsan", 18); p1("hello world"); myAdd myadd; cout << myadd(18, 16) << endl;
cout << myAdd()(100, 100) << endl; }
|
4.6 继承
4.6.1 继承的基本语法
继承的好处:减少重复代码
语法:class 子类:继承方式 父类
子类也称为派生类
父类也称为基类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #include <iostream> #include "class127_继承.h" using namespace std;
class BasePage { public: void header() { cout << "toubu" << endl; } void footer() { cout << "底部" << endl; } void left() { cout << "左侧" << endl; } };
class Java :public BasePage { public: void content() { cout << "java" << endl; } }; int main() { test01(); }
void test01() { Java ja; ja.header(); ja.footer(); ja.left(); ja.content(); }
|
4.6.2 继承方式
继承方式一共有三种:
·公共继承
保护继承
·私有继承
img
4.6.3 继承中的对象模型
父类中所以非静态成员属性都会被子类继承下去
img
4.6.4 继承中的构造和析构顺序
构造 先父类后子类
析构 先子类后父类
4.6.5 继承同名成员处理方式
img
img
父类需要加Base::
4.6.6 同名静态成员处理
静态成员和耳非静态成员出现同名,处理方式一致
·访问子类同名成员直接访问即可
·访问父类同名成员需要加作用域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <iostream> using namespace std;
class Base { public: static int a; static void func() { cout << "base func" << endl; } }; int Base::a = 100;
class Son : public Base { public: static int a; static void func() { cout << "Son func" << endl; } }; int Son::a = 200; void test() { Son s; cout << s.a << endl; cout << s.Base::a << endl; cout << Son::a << endl; cout << Son::Base::a << endl;
s.func(); s.Base::func();
Son::func(); Son::Base::func(); } int main() { test(); }
|
4.6.7 多继承语法
C++允许一个类继承多个类
语法:class 子类 : 继承方式 父类1,继承方式 父类2,
多继承可能会引发父类中有同名成员出现,需要加作用域区分
C++实际开发中不建议用多继承
4.6.8 菱形继承
img
img
img
img
img
img
4.7 多态
4.7.1 多态基本概念
多态是c++面向对象三大特性之
多态分为两类
静态多态:函救重载和运算符重载属于静态多态,复用函数名
动态多态:派生类和虚函数实现运行时多态
静态多态和动态多态区别:
静态多态的感数地址早绑定,编泽阶段确定团数地址
动态多态的函数地址晚绑定-运行阶段确定函教地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include <iostream> using namespace std;
class Animal { public : virtual void speak() { cout << "animal speak" << endl; } };
class Cat : public Animal { public: virtual void speak() { cout << "cat speak" << endl; } };
void doSpeak(Animal &animal) { animal.speak();
} int main() { Cat cat; doSpeak(cat); }
|
总结:
多态满足条件
·有继承关系
·子类重写父类中的虚函数
多态使用条件
·父类指针或引用指向子类对象
重写:函数返回值类型函数名参数列表完全一致称为重写
4.7.2 多态案例一、计算机类
案例描述:
分别利用普通写法和多态技术,设计实现两个操作数进行运算的计算器类
多态的优点:
· 代码组织结构清晰
` 可读性强
· 利于前期和后期的扩展以及维护
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <iostream> using namespace std;
class Abstract { public: virtual int getResult() { return 0; } int num1; int num2; };
class AddCalculator : public Abstract { public:
int getResult() { return num1 + num2; } };
class SubCalculator : public Abstract { public:
int getResult() { return num1 - num2; } };
int main() { Abstract* abs = new AddCalculator; abs->num1 = 20; abs->num2 = 20; cout << abs->getResult() << endl; delete abs; abs = new SubCalculator; abs->num1 = 20; abs->num2 = 20; cout << abs->getResult() << endl; delete abs; }
|
4.7.3 纯虚函数和抽象类
在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数
纯虚函数语法:virtual 返回值类型 函数名(参数列表)=0;
当类中有了纯虚函数,这个类也称为抽象类
抽象类特点:
·无法实例化对象
·子类必须重写抽象类中的纯虚函数,否则也属于抽象类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <iostream> using namespace std;
class Base { public: virtual void func() = 0; };
class Son : public Base { public: virtual void func() { cout << "func" << endl; } };
int main() { Base* base = new Son; base->func(); delete base; }
|
4.7.4 多态案例二:制作饮品
案例描述:
制作饮品的大致流程为:煮水·冲泡·倒入杯中·加入辅料
利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| #include <iostream> using namespace std;
class Drinking { 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 Drinking { public: virtual void Boil() { cout << "煮农夫山泉" << endl; } virtual void Brew() { cout << "冲泡咖啡" << endl; } virtual void PourInCup() { cout << "倒入杯中" << endl; } virtual void PutSomething() { cout << "加入糖和牛奶" << endl; } };
class Tea : public Drinking { public: virtual void Boil() { cout << "煮矿泉水" << endl; } virtual void Brew() { cout << "冲泡茶叶" << endl; } virtual void PourInCup() { cout << "倒入杯中" << endl; } virtual void PutSomething() { cout << "加入柠檬" << endl; } };
void doWork(Drinking* d) { d->MakeDrink(); delete d; } int main() { doWork(new Coffee); doWork(new Tea); }
|
4.7.5 虚析构和纯虚析构
多态使用时,如果子类中有属性开辩到堆区,那么父类指针在释放时无法调用到子类的析构代码
解决方式:将父类中的析构函数双为析所构或老纯虚析构
虚析构和纯虚析构共性:
·可以解决类指针释放子类对象
·都需要有具体的函数实现
虚析构和纯虚析构区别:
·如果是纯虚析构,该类属于抽象类,无法实例化对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <iostream> using namespace std;
class Animal { public: virtual void Speak() = 0; virtual ~Animal() = 0; }; Animal::~Animal() { cout << "chunxigou" << endl; } class Cat : public Animal { public: Cat(string m_name) { name = new string(m_name); } virtual void Speak() { cout << "miaomiao" << endl; } ~Cat() { if (name != NULL) { delete name; name = NULL; cout << "xigou" << endl; } } string *name; };
int main() { Animal* ani = new Cat("Tom"); ani->Speak(); delete ani; }
|
总结:
1.虚析构或纯空析构就是用来解决通过父类指针释放子类对象
2.如果子类中没有堆区数据,可以不写为虚析构或纯虚析构
3,用有纯虚析构函数的类也属于抽象类
4.7.6 多态案例三 电脑组装
电脑主要组成部件为CPU(用于计算),显卡〔用于显示),内存条(用于存储)
将每个零件封装出抽象基类,并目提供不同的厂商生产不同的零件,例如Intel)厂商和Lenovo厂商
创建电脑类提供让电脑工作的函数井且调用每个零件工作的接口
测试时组装三台不同的电脑进行工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
| #include <iostream> using namespace std;
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* m_cpu, VideoCard* m_vc, Memory* m_mem) { cpu = m_cpu; vc = m_vc; mem = m_mem; } void work() { cpu->Calculate(); vc->Display(); mem->Storage(); } ~Computer() { if (cpu != NULL) { delete cpu; cpu = NULL; } if (vc != NULL) { delete vc; vc = NULL; } if (mem != NULL) { delete mem; mem = NULL; } } private: Cpu* cpu; VideoCard* vc; Memory* mem;
};
class IntelCpu : public Cpu { public: virtual void Calculate() { cout << "intel cpu cal" << endl; }
}; class Intelvc : public VideoCard { public: virtual void Display() { cout << "intel cpu display" << endl; }
};
class IntelMemory : public Memory { public: virtual void Storage() { cout << "intel cpu cal" << endl; } };
class LenovoCpu : public Cpu { public: virtual void Calculate() { cout << "Lenovo cpu cal" << endl; }
}; class Lenovovc : public VideoCard { public: virtual void Display() { cout << "Lenovo display" << endl; }
};
class LenovoMemory : public Memory { public: virtual void Storage() { cout << "Lenovo storage" << endl; } };
void test() { Cpu* intelCpu = new IntelCpu; VideoCard* intelvc = new Intelvc; Memory* intelMemory = new IntelMemory;
Computer* computer1 = new Computer(intelCpu, intelvc, intelMemory); computer1->work(); delete computer1;
Computer* computer2 = new Computer(new LenovoCpu, new Lenovovc, new LenovoMemory); computer2->work(); delete computer2; } int main() { test(); }
|