目录
继承实现
被继承的类称为基类也被称为超类;从基类派生而来的类称为派生类,也叫子类
#include <iostream>
using namespace std;
class Fish
{
public:
bool FreshWaterFish;
void Swim()
{
if (FreshWaterFish)
cout << "Swims in lake" << endl;
else
cout << "Swims in sea" << endl;
}
};
//Tuna继承了Fish
class Tuna :public Fish
{
public:
Tuna()
{
FreshWaterFish = false;
}
};
//Carp继承了Fish
class Carp :public Fish
{
public:
Carp()
{
FreshWaterFish = true;
}
};
int main()
{
Carp myLunch;
Tuna myDinner;
cout << "Lunch: ";
myLunch.Swim();
cout << "Dinner: ";
myDinner.Swim();
system("pause");
return 0;
}
PS:继承还是不难的,通俗理解就是利用已有的类来构造新的类。
访问限定符protected
如果我想让基类的某些属性能在派生类中访问,但不能在继承层次结构外部访问。就需要用到protected。还以上面的那个代码为例,我希望Fish类的布尔标记FreshWaterFish可在派生类Tuna和Carp中访问,但不能在实例化Tuna和Carp的main()中访问,就需要protect。稍作修改如下:
#include <iostream>
using namespace std;
class Fish
{
protected: //更改之处
bool FreshWaterFish;
public:
void Swim()
{
if (FreshWaterFish)
cout << "Swims in lake" << endl;
else
cout << "Swims in sea" << endl;
}
};
//Tuna继承了Fish
class Tuna :public Fish
{
public:
Tuna()
{
FreshWaterFish = false;
}
};
//Carp继承了Fish
class Carp :public Fish
{
public:
Carp()
{
FreshWaterFish = true;
}
};
int main()
{
Carp myLunch;
Tuna myDinner;
cout << "Lunch: ";
myLunch.Swim();
cout << "Dinner: ";
myDinner.Swim();
system("pause");
//myLunch.FreshWaterFish = false;
return 0;
}
如果把Main函数里面的哪一行注释掉,就会报错, 因为FreshWaterFish是被保护了,从main中无法访问。
基类初始化
如果基类包含重载的构造函数,需要在实例化的时候给它提供实参,这个时候,创建派生对象时用初始化列表的方法,通过派生类的构造函数调用合适的基类构造函数。
在派生类中覆盖基类
如果派生类实现了从基类继承的函数,且返回值和特征标相同,就相当于覆盖了基类的这个方法。当然,如果还是想调用基类的也可以,就是myDinner.Fish::Swim(),就可以了。
#include <iostream>
using namespace std;
class Fish
{
protected: //更改之处
bool FreshWaterFish;
public:
void Swim()
{
if (FreshWaterFish)
cout << "Swims in lake" << endl;
else
cout << "Swims in sea" << endl;
}
};
//Tuna继承了Fish
class Tuna :public Fish
{
public:
Tuna()
{
FreshWaterFish = false;
}
};
//Carp继承了Fish
class Carp :public Fish
{
public:
void Swim()
{
cout << "Carp swims real slow" << endl;//这行将原来基类里的函数同名,并且,改写了,调用的时候以这个为输出
}
Carp()
{
FreshWaterFish = true;
}
};
int main()
{
Carp myLunch;
Tuna myDinner;
cout << "Lunch: ";
myLunch.Swim();
//调用派生类中Swim
cout << "Dinner: ";
myDinner.Swim();
//还是想调用基类中Swim
cout << "Dinner: ";
myDinner.Fish::Swim();
system("pause");
//myLunch.FreshWaterFish = false;
return 0;
}
在派生类中重复调用基类的函数,也是可以的:
构造与析构顺序
基类对象在派生类对象之前被实例化。先实例化成员属性,再调用构造函数,确保成员属性准备就绪,可供构造函数使用。
而析构的顺序与构造的顺序相反,先析构派生类对象再析构基类对象。
私有继承
要另外再派生类里面再开个函数(SS)来放,想调用的基类函数:
#include <iostream>
using namespace std;
class Fish
{
protected: //更改之处
bool FreshWaterFish;
public:
void Swim()
{
if (FreshWaterFish)
cout << "Swims in lake" << endl;
else
cout << "Swims in sea" << endl;
}
};
//Tuna继承了Fish
class Tuna :private Fish
{
public:
void SS() //这里必须另外构造一个函数,把基类的函数放到这里面,然后,调用这个函数,但不能显示基类的函数。
{
Swim();
}
};
int main()
{
Tuna myDinner;
cout << "Lunch: ";
myDinner.SS();
system("pause");
//myLunch.FreshWaterFish = false;
return 0;
}
正常的继承关系是:基类->派生类->派生类实例化
public调用的时候:派生类实例化可以调用基类成员函数,也能调用派生类的成员函数;
pravate调用的时候:派生类实例化可以调用派生类的函数,不能调用基类成员函数;且派生类函数可调用基类的函数。
保护继承
就是基类产生的派生类的派生类还是可以跟第一代派生类相同权限的,但不能直接在派生类的实例化函数里调用基类的成员函数,但private是不可以的,只能第一代有权访问基类成员函数。
PS:仅当必要的时候才使用私有或者保护继承。
切除问题
不要按值传递参数,哟啊以指针或者引用来传递,还是指向基类的指针和const的引用。
多继承
语法:
has-a和is-a关系的举例
我们常见的动物,羊有很多种类,只是一种泛指,绵羊是其中一种,那么羊和绵羊的关系,就是is-a,即它们是继承的关系。
再如,羊身上都有羊毛,而不同种类的羊,羊毛生物形态也不同,比如绵羊和羚羊,前者羊毛丰富、蓬松、柔软,呈白色;后者羊毛稀少、刚硬,呈灰褐色。对于绵羊来说,羊毛和羊的关系就是has-a。对于羚羊也是同理。我们可以根据羊毛的不同,来区别羊的品种。
用自然语言来表述二者:
is-a: 这种事物(绵羊)是那种事物(羊)中的一个种类。
has-a:这种事物(羊毛)隶属于那种事物(绵羊),是它的一个部分、部件。