继承是面向对象三大特性之一
有些类与类之间存在特殊的关系,例如下图中:
我们发现,定义这些类时,下级别的成员除了拥有上一级的共性,还有自己的特性。
这个时候我们就可以考虑利用继承的技术,减少重复代码
例如我们看到很多网站中,都有公共的头部,公共的底部,甚至公共的左侧列表,只有中心内容不同。接下来我们分别利用普通写法和继承的写法来实现网页中的内容,看一下继承存在的意义以及好处。
普通实现:
#include
using namespace std;
class javapage
{
public:
void common()
{
cout << "通用界面" << endl;
}
void javashow()
{
cout << "java" << endl;
}
};
class cpppage
{
public:
void common()
{
cout << "通用界面" << endl;
}
void cppshow()
{
cout << "cpp" << endl;
}
};
class pythonpage
{
public:
void common()
{
cout << "通用界面" << endl;
}
void pythonshow()
{
cout << "python" << endl;
}
};
int main()
{
javapage jav;
jav.common();
jav.javashow();
cout << "------------" << endl;
cpppage cp;
cp.common();
cp.cppshow();
cout << "------------" << endl;
pythonpage py;
py.common();
py.pythonshow();
system("pause");
return 0;
}
继承实现:
#include
using namespace std;
class page
{
public:
void show()
{
cout << "基类的通用界面" << endl;
}
};
class jpage : public page
{
public:
void jshow()
{
cout << "java" << endl;
}
};
class cpage : public page
{
public :
void cshow()
{
cout << "cpp" << endl;
}
};
class ppage : public page
{
public:
void pshow()
{
cout << "python" << endl;
}
};
int main()
{
jpage jav;
jav.show();
jav.jshow();
cout << "------------" << endl;
cpage cp;
cp.show();
cp.cshow();
cout << "------------" << endl;
ppage py;
py.show();
py.pshow();
system("pause");
return 0;
}
继承的好处:减少重复代码
class A : public B
{
public:
protected:
private:
}
A 类称为子类 或 派生类
B 类称为父类 或 基类
public称为继承方式
继承的语法:
class 子类 : 继承方式 父类
继承方式一共有三种:
从父类继承过来的成员,哪些属于子类对象中?
#include
using namespace std;
class page
{
public:
void show()
{
cout << "基类的通用界面" << endl;
}
int a;
private:
int e;
};
class jpage : public page
{
public:
void jshow()
{
cout << "java" << endl;
}
int b;
};
class cpage : public page
{
public :
void cshow()
{
cout << "cpp" << endl;
}
int c;
};
class ppage : public page
{
public:
void pshow()
{
cout << "python" << endl;
}
int d;
};
int main()
{
jpage jav;
jav.show();
jav.jshow();
cout << "------------" << endl;
cpage cp;
cp.show();
cp.cshow();
cout << "------------" << endl;
ppage py;
py.show();
py.pshow();
system("pause");
return 0;
}
打开工具窗口后,定位到当前CPP文件的盘符
然后输入: cl /d1 reportSingleClassLayout查看的类名 所属文件名
a,e是父类继承过来的
bcd是子类特有的
父类中私有成员e也是被子类继承下去了,只是由编译器给隐藏后访问不到
子类继承父类后,当创建子类对象,也会调用父类的构造函数
问题:父类和子类的构造和析构顺序是谁先谁后?
#include
using namespace std;
class base
{
public:
base()
{
cout << "base 构造函数" << endl;
}
~base()
{
cout << "base 析构函数" << endl;
}
};
class child : public base
{
public:
child()
{
cout << "child 构造函数" << endl;
}
~child()
{
cout << "child 析构函数" << endl;
}
};
void test()
{
child chil;
}
int main()
{
test();
system("pause");
return 0;
}
继承中 先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反
当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据呢?
出现同名,子类会隐藏掉父类中的所有同名成员函数,加作用域访问。
//通过对象访问
child.a;
child.base::a;
问题:继承中同名的静态成员在子类对象上如何进行访问?
静态成员和非静态成员出现同名,处理方式一致
//通过对象访问
child.a;
child.base::a;
//通过类名访问 静态变量tsatic int a可以通过类名访问
child::a;
child::base::a;
C++允许一个类继承多个类
语法:class 子类 :继承方式 父类1 , 继承方式 父类2…
多继承可能会引发父类中有同名成员出现,需要加作用域区分
C++实际开发中不建议用多继承
#include
using namespace std;
class base1
{
public:
base1()
{
a = 100;
}
int a;
};
class base2
{
public:
base2()
{
a = 200;
}
int a;
};
class son : public base1, public base2
{
public:
son()
{
a = 0;
c = 300;
d = 400;
}
int c;
int d;
int a;
};
void test1()
{
son s;
cout << "" << sizeof(s) << endl;
cout << s.base1::a << endl;
cout << s.base2::a << endl;
}
int main()
{
test1();
system("pause");
return 0;
}
多继承中如果父类中出现了同名情况,子类使用时候要加作用域
菱形继承概念:
两个派生类继承同一个基类
又有某个类同时继承者两个派生类
这种继承被称为菱形继承,或者钻石继承
如图:
菱形继承问题:
#include
using namespace std;
class animal
{
public:
int age;
};
//继承前加virtual关键字后,变为虚继承
//此时公共的父类Animal称为虚基类
class sheep : virtual public animal
{
};
class tuo : virtual public animal
{
};
class yangtuo : public sheep, public tuo
{
};
void test2()
{
yangtuo yangtu;
yangtu.sheep::age = 100;
yangtu.tuo::age = 200;
cout << "sheep:" << yangtu.sheep::age << endl;
cout << "tuo:" << yangtu.tuo::age << endl;
cout << "yangtuo:" << yangtu.age << endl;
}
int main()
{
test2();
system("pause");
return 0;
}
运行结果:只有一个age变量
使用开发工具打印单一类布局:
vbptr:virtual base pointer 虚基指针,是一个偏移量
它指向vbtable虚基表
菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义
利用虚继承可以解决菱形继承问题