今天突然发现自己关于类的继承,虚基类,访问权限混在在一起的时候有有一些模糊,所以今天进行重新学习一下。如果错误或者不对的地方,还请指教。
一、类的继承方式
类有三种成员成员,private,protected,public,
基类的成员 | 派生方式 | 子类访问特性 |
public protected private | public | public protected NO Access |
public protected private | protected | protected protected No Access |
public protected private | private | private private No Access |
类的成员访问权限 | public | protected | private |
访问特性 | 类的成员函数、类的成员变量,都可以通过类的成员函数或类的实例化进行访问 | 可以被类的成员函数进行访问,子类的函数,友元函数进行访问。 | 成员函数、成员变量不能被类的实例化进行访问,只能被类的成员函数访问,友元函数访问 |
有人就会问那protected和private的区别是什么了,有的地方的解释,在类外是一样的,“类外”这个描述把有的初学者给搞晕了,protected和private都可以被类的成员函数内进行访问,访问的方式可以通过this->...还有友元访问,但是区别就是private是到不了子类的,而protected是可以到子类的,这是为什么很多博客在写这两者的区别的时候,protected增加一条子类的访问。
二、虚继承、虚函数
类的对象在实例化的时候会调用构造函数,那么子类的构造函数的调用顺序是怎么样的,直接上代码。
class A {
public:
A() {cout << "A" ;}
~A() {cout << "~A" ;}
};
class B {
public:
B() {cout << "B" ;}
~B() {cout << "~B";}
private:
A a;
};
class C : public A {
public:
C() {cout << "C" ;}
~C() {cout << "~C";}
private:
B b;
A a;
};
int main()
{
cout << "=======================================\n";
cout << "A类对象的构造过程: ";
A a;
cout << "\n======================================\n\n";
cout << "B类对象的构造过程: " ;
B b;
cout << "\n=======================================\n\n";
cout << "C类对象的构造过程: ";
C p ;
cout << "\n=======================================\n";
return 0;
}
很明显构造顺序为: 父类的构造函数->组合成员对象的构造函数 ->子类自己的构造函数,类成原变量的空间分配及初始化是在调用自己构造函数之前进行的,他们的声明初始化顺序由声明顺序决定。
现在来看一下什么是虚继承,
class A
{
public:
int k;
}
class B:public A
{
};
class C:public A
{
};
class D:public C,public D
{
};
如果D是实例化的时候访问k,这个k到底是B继承来的还是C继承来的? 这就出现二义性,其实虚继承就是为了解决这个二义性而产生的,为了只让基类保存一个这样的副本,就声明为虚继承,这样就只是保存了一个副本。
虚函数又是这么回事? http://blog.youkuaiyun.com/haoel/article/details/1948051/ 这篇文章和清晰的讲解了虚函数的继承,覆盖并从内存面解释虚表,其中 一般继承(有虚函数的覆盖),基类的实例a和子类的实例b访问就会根据虚表来进行调用。
说到虚函数肯定会讲到纯虚函数,①纯虚函数没有函数体 ②纯虚函数的作用是在基类中留下一个空间,以便派生类对他进行定义 ③ 如果子类没有对基类的纯虚函数进行实现,那么这个函数任然是纯虚函数,这个类任然是抽象类。
跟纯虚函数相关又是抽象类,抽象类是不能被实例化的,纯虚函数在派生类中实现后,派生类才能实例化出对象,作为一种基本类型用作继承,凡是包含纯虚函数的都是抽象类。
作者能力有限,如有错误,还请指出。