在C++里,通过继承和组合实现了代码复用,使得开发效率提高,并且能够通过代码看到事物的关系
组合比继承简单,所以在写代码时先考虑能否组合,再来考虑继承.
组合的特点
- 将其它类的对象作为当前类的成员使用
比如主机类,拥有 CPU/主板/内存/硬盘这4个对象成员,而这4个对象成员并没有继承主机类的特性和行为
继承的特点
- 新的类(子类)具有旧的类(父类)的属性和行为
- 旧的类被称为父类,也叫基类
- 新的类被称为子类,也叫派生类(一个派生类也可以继承多个基类)
- 子类可以添加新的属性和行为(成员变量和成员函数),也可以重写已有的属性和行为
- 一个子类只继承一个父类,便被称为单继承
- 一个子类若继承多个父类,便被称为多继承
- 子类其实就是一个特殊的父类,比如:苹果手机是手机,就是将苹果手机当做一个特殊的父类对待
子类对象可以初始化父类对象,也可以赋值给父类对象,比如:
class Parent
{
int mValue;
public:
Parent()
{
mValue=;
}
int Value()
{
return mValue;
}
}; class Child : public Parent
{
public:
Child()
{
cout<<"I'm child"<<endl;
}
}; int main()
{
Child c;
cout<< c.Value() <<endl; //调用父类的成员函数 Parent p1 =c; //通过子类初始化父类 Parent p2; p2=c; //通过子类复制给父类
}
类的访问级别之protected
大家都知道,类里private修饰的成员和函数,不能被外界直接访问.
虽然子类拥有父类的属性和行为,但是在子类里,也不能访问父类的private私有成员
比如:
class Parent
{
int mValue;
public:
Parent(int i=)
{
mValue=i;
}
int Value()
{
return mValue;
}
}; class Child : public Parent
{
public:
Child()
{
cout<<mValue<<endl; //在子类中,访问父类的private成员,将会编译报错
}
};
所以类的访问级别引入了新的关键字protected
protected的特性
- 修饰的成员不能被外界直接访问
- 修饰的成员可以被子类(包括子类的子类)直接访问, 也可以在本类内部直接访问
有了protected的加入,定义类时,我们就需要仔细考虑成员的访问级别,如下图所示:
接下来做个综合实例,组合与继承
- 需要一个父类Object, 为子类Point和子类Line 提供name名字和info信息
- 由于线Line至少需要两个点Point才能组成,所以Line子类内部需要通过Point子类来组合
如下图所示:
开始写代码:
#include <iostream>
#include <string>
#include <sstream> using namespace std; class Object
{
protected:
string mName;
string mInfo;
public:
Object()
{
mName="Object";
mInfo="";
}
string name()
{
return mName;
}
string info()
{
return mInfo;
}
}; class Point : public Object
{
protected:
int x; //坐标
int y; public:
Point(int x=,int y=)
{
ostringstream s;
this->x =x;
this->y =y;
s<<"P("<<x<<","<<y<<")"; //坐标信息
mName="Point";
mInfo=s.str();
}
}; class Line : public Object
{
private:
Point mP1;
Point mP2;
public:
Line(Point p1,Point p2)
{
ostringstream s;
mP1 =p1;
mP2 =p2;
s<<"Line from " <<p1.info() <<" to "<<p2.info(); //线的信息
mName ="Line";
mInfo =s.str();
}
}; int main()
{
Point p1(,);
Point p2(,);
Line L(p1,p2);
/*打印点的信息*/
cout<<p1.name()<<":"<<endl;
cout<<p1.info()<<endl; /*打印线的信息*/
cout<<L.name()<<":"<<endl;
cout<<L.info()<<endl;
return ;
}
运行打印:
Point:
P(,) Line:
Line from P(,) to P(,)