总结:
1、子类对象可以当做父类对象使用
2、子类对象可以直接赋值给父类对象
3、子类对象能够直接初始化父类对象
4、父类指针可以直接指向子类对象
5、凡是继承过来的属性和函数都可以在子类中用this-> 进行访问
6、默认构造函数并不会初始化数据成员
7、如果子类数据成员和父类数据成员名称相同。在子类用利用:: 访问父类数据成员,this-> 默认为子类数据成员
8、构造函数和析构函数不会被继承
一、类型兼容性规则
类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代。通过公有继承,派生类得到了基类中除构造函数、析构函数之外的所有成员。这样,公有派生类实际就具备了基类的所有功能,凡是基类能解决的问题,公有派生类都可以解决。
类型兼容规则中所指的替代包括以下情况:
<1>子类对象可以当作父类对象使用
<2>子类对象可以直接赋值给父类对象
<3>子类对象可以直接初始化父类对象
<4>父类指针可以直接指向子类对象
<5>父类引用可以直接引用子类对象
继承模型:
在子类对象构造时,需要调用父类构造函数对其继承得来的成员进行初始化.
在子类对象析构时,需要调用父类析构函数对其继承得来的成员进行清理.
二、继承中构造析构调用原则
1、子类对象在创建时会首先调用父类的构造函数
2、父类构造函数执行结束后,执行子类的构造函数
3、当父类的构造函数有参数时,需要在子类的初始化列表中显示调用
4、析构函数调用的先后顺序与构造函数相反
总原则:
先构造父类,再构造成员变量、最后构造自己
先析构自己,在析构成员变量、最后析构父类
三、继承中同名成员变量处理方法
1、当子类成员变量与父类成员变量同名时 ,子类依然从父类继承同名成员
2、在子类中通过作用域分辨符::进行同名成员区分(在派生类中使用基类的同名成员,显式地使用类名限定符)
注:同名成员存储在内存中的不同位置
四、派生类中的static关键字
1、基类定义的静态成员,将被所有派生类共享
2、根据静态成员自身的访问特性和派生类的继承方式,在类层次体系中具有不同的访问性质 (遵守派生类的访问控制)
3、 派生类中访问静态成员,用以下形式显式说明:
类名 :: 成员
或通过对象访问 对象名 . 成员
示例:
1、类的兼容性规则
#if 1
#include<iostream>
using namespace std;class Parent {
public:void printP() {cout << "a:" << this->a << endl;}int a;
};
class Child :public Parent {
public:/*void printP() {cout << "b:" << this->b << endl;}*/void printC() {cout << "b:" << this->b << endl;}int b;
};
void test01() {Parent *p = new Child;p->printP(); //子类和父类都有printP函数时,调用父类的成员函数
}
//子类对象可以当做父类对象使用
//子类对象可以直接赋值给父类对象
//子类对象能够直接初始化父类对象
void test02() {Parent p; //父类空间小//Child c = p; //子类空间大于父类,不能够全部初始化,所以报错Child c;Parent p = c; //c对象占用空间>=p对象占用空间 //能够填充可以通过编译//子类对象能够直接初始化父类对象c.printP(); //c能够当做父类p来使用}
//父类指针可以直接指向子类对象
//好处:
void test03() {Parent *pp = NULL; //父类指针Child *cp = NULL; //子类指针Parent p; //父类对象Child c; //子类对象cp = &c;//cp = &p; 子类指针指向父类对象 错误 子类指针访问范围大于父类对象的范围//原来cp的访问权限为cp->a,cp->b,cp->printP.cp->printC//cp指向p时,cp的访问权限只能为cp->a,cp->printP//会访问越界pp = &p;pp = &c; //通过编译 父类指针指向子类对象//原来cp的访问权限为pp->a; pp->printP//pp指向c时,cp的访问权限扔为pp->a; pp->printP//c内存布局能够满足父类指针的全部需求 可以用一个儿子的对象地址给父类指针赋值}
int main() {return 0;
}
#endif
2、构造函数和析构函数
#if 0
#include<iostream>
using namespace std;
//在调用子类的构造函数时 一定会调用父类的构造函数
//父类先构造,子类再构造
//析构和构造顺序相反
class Parent {
public:Parent() {cout << "Parent()... " << endl;a = 0;}Parent(int a) {cout << "Parent(int a)..." << endl;this->a = a;}int a;~Parent() {cout << "~Parent()..." << endl;}
};
class Child :public Parent {
public://在调用子类的构造函数时 编译器会默认调用父类无参构造
#if 0Child(int a,int b) {cout << "Child(int a,int b)..." << endl;this->a = a;this->b = b;}
#endif//显示调用父类有参构造Child(int a ,int b):Parent(a){cout << "Child(int a,int b)..." << endl;this->b = b;}~Child() {cout << "~Child()... " << endl;}void printC() {cout << "b=" << b << endl;}int b;
};//在调用子类时 编译器会默认调用父类无参构造
void test01() {Child c(10, 20);c.printC();
}
/*
Parent()...
Child(int a,int b)...
b=20
~Child()...
~Parent()...
*/
//显示调用父类有参构造
void test02() {Child c(10, 20);c.printC();
}
/*
Parent(int a)...
Child(int a,int b)...
b=20
~Child()...
~Parent()...
*/
int main() {test01();return 0;
}
#endif
3、子类和父类成员重名
#if 0
#include<iostream>
using namespace std;
#if 0
class Parent {
public:Parent() {cout << "Parent() " << endl;this->a = 0;}Parent(int a) {cout << "Parent(int a) " << endl;this->a = a;}~Parent() {cout << "析构父类a:" << this->a << endl;}int a;
};
class Child :public Parent {
public:int a;Child(int a) {cout << "Child(int a)" << endl;this->a = a;}~Child() {cout << "析构子类a:" << this->a << endl;}
};void test01() {Child c(2);
}
/*
Parent()
Child(int a)
析构子类a:2
析构父类a:0
*/
#endif
#if 0
class Parent {
public:Parent(int a) {cout << "Parent(int a) " << endl;this->a = a;}~Parent() {cout << "析构父类a:" << this->a << endl;}int a;
};
class Child :public Parent {
public:int a;Child(int p_a,int c_a):Parent(p_a){cout << "Child(int a)" << endl;this->a = c_a;}~Child() {cout << "析构子类a:" << this->a << endl;}void print() {cout << "父类a:"<<Parent::a << endl;cout <<"子类a:" <<this->a << endl; //子类的a}
};void test01() {Child c(2,3);c.print();
}
/*
Parent(int a)
Child(int a)
父类a:2
子类a:3
析构子类a:3
析构父类a:2
*/
#endif
//子类和父类函数名相同调用
class Parent {
public:Parent(int a) {cout << "Parent(int a) " << endl;this->a = a;}void print() {cout << "父类print" << endl;}~Parent() {cout << "析构父类a:" << this->a << endl;}int a;
};
class Child :public Parent {
public:int a;Child(int p_a, int c_a) :Parent(p_a) {cout << "Child(int a)" << endl;this->a = c_a;}~Child() {cout << "析构子类a:" << this->a << endl;}void print() {cout << "子类print" << endl; //子类的a}
};void test01() {Parent p(1);p.print();cout << "------" << endl;Child c(2, 3);c.Parent::print();c.print();
}
/*
Parent(int a)
父类print
------
Parent(int a)
Child(int a)
父类print
子类print
析构子类a:3
析构父类a:2
析构父类a:1
*/
int main() {test01();return 0;
}
#endif
4、继承中的static成员
#if 1
#include<iostream>
using namespace std;
#if 0
class A {
public:static int a;
private:
};
int A::a = 0; //静态成员变量 初始化void test01()
{A a1;A a2;cout << a1.a << endl;cout << a2.a << endl;a1.a = 300;cout << a1.a << endl;cout << a2.a << endl;
}
/*
0
0
300
300
*/
#endifclass A {
public:static int a;
private:
};
class B :public A {
public:
private:
};
int A::a = 0; //静态成员变量 初始化void test01()
{A a1;A a2;cout << a1.a << endl;cout << a2.a << endl;a1.a = 300;cout << a1.a << endl;cout << a2.a << endl;B b1;B b2;cout << b1.a << endl;cout << b2.a << endl;A::a = 400;cout << b1.a << endl;cout << b2.a << endl;
}
/*
0
0
300
300
300
300
400
400
*/
int main() {test01();return 0;
}
#endif