一、基类 & 派生类
面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行效率的效果。
嗯.恩~。。,相当于没说。为了通俗一点,我们举一个栗子:
我们创建一个基类“Father”。父亲有他的私房钱(Private)他也有自己的生存技能,假如他也是一名程序猿,他有他的it_skill(public),他还可以改变自己的私房钱 setMoney(int money),获取自己的私房钱 getMoney(void)。
class Father {
private:
int money;
protected:
int room_key;
public:
void it_skill(void)
{
cout<<"father's it skill"<<endl;
}
int getMoney(void)
{
return money;
}
void setMoney(int money)
{
this->money = money;
}
};
再创建一个派生类“Son”,儿子“Son”继承于父亲“Father”,儿子有他的玩具toy(private),他喜欢玩游戏void play_game(void)。
class Son : public Father {
private:
int toy;
public:
void play_game(void)
{
int m;
cout<<"son paly game"<<endl;
/* money -= 1;
* 错: 不能直接拿父亲的私房钱
*/
/*
* 但是可以问他要
*/
m = getMoney();
m--;
setMoney(m);
room_key = 1;
}
};
儿子继承于父亲,儿子可以继承父亲的公有属性部分,但是无法访问私有部分。父亲存点私房钱也不容易,儿子不能把手伸到他口袋里拿,而且父亲的私房钱儿子都不知道在哪,是没办法访问的,但是儿子通过公有函数向父亲要。
Father中 还有一个类成员变量room_key,它的的属性是Protect,Protect属性的部分派生类能够访问,但是外部不能访问。也就是说父亲的房间要是父亲把他保护起来的,儿子可以是由,但是外人不可以。
继承有以下几种属性的继承,不同的方式访问权限不同:
当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。继承类型是通过上面讲解的访问修饰符 access-specifier 来指定的。
我们几乎不使用 protected 或 private 继承,通常使用 public 继承。当使用不同类型的继承时,遵循以下几个规则:
- 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
- 保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
- 私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。
二、 多重继承
多继承就是一个派生类继承于多个基类,基本格式就像这样:
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
};
我们还是举一个栗子,我们要创建一个沙发床类Sofabed,那么它就既有沙发Sofa的特征也有床Bed的特征。
class Sofa {
public:
void watchTV(void) { cout<<"watch TV"<<endl; }
};
class Bed {
public:
void sleep(void) { cout<<"sleep"<<endl; }
};
class Sofabed : public Sofa, public Bed {
};
int main(int argc, char **argv)
{
Sofabed s;
s.watchTV();
s.sleep();
return 0;
}
问题来了,如果Sofa 有重量weight,Bed 也有重量weight,Sofabed 不就有了两个重量了吗?这显然不符合现实啊,为了就觉这个问题我们引入了虚拟继承。
我们要先创建一个家具类Furniture ,Sofa 和Bed都虚拟继承于Furniture,Sofabed 继承Sofa和Bed这时候两个重量weight就共用了同一块内存。
#include <iostream>
#include <string.h>
#include <unistd.h>
using namespace std;
class Furniture {
private:
int weight;
public:
void setWeight(int weight) { this->weight = weight; }
int getWeight(void) const { return weight; }
};
class Sofa : virtual public Furniture {
private:
int a;
public:
void watchTV(void) { cout<<"watch TV"<<endl; }
};
class Bed : virtual public Furniture {
private:
int b;
public:
void sleep(void) { cout<<"sleep"<<endl; }
};
class Sofabed : public Sofa, public Bed {
private:
int c;
};
int main(int argc, char **argv)
{
Sofabed s;
s.watchTV();
s.sleep();
s.setWeight(100);
return 0;
}
不过在C++中多重继承是不推荐的也不常用的。