总结:
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 0
Child(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
*/
#endif
class 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