继承方式的不同,成员变量在子类中的权限不同
继承方式 | public | protected | private |
public | public | protected | private |
protected | protected | proteced | private |
private | private | private | private |
1、子类拥有父类中所有成员变量和成员函数
2、子类就是一种特殊的父类
3、子类对象可以当做父类对象使用
4、子类也可以拥有父类没有的方法和属性
赋值兼容性原则
1、子类对象可以当做父类对象使用
2、子类对象可以直接赋值给父类对象
3、子类对象可以直接初始化父类对象
4、父类指针可以直接指向子类对象
5、父类引用可以直接引用子类对象
namespace three {
class Parent {
public:
void printP() {
printf("i am father\n");
}
protected:
int a;
int b;
};
class Child :public Parent {
public:
Child() {
a = 0;
b = 0;
c = 0;
}
void printC() {
printf("i am son\n");
}
protected:
private:
int c;
};
void howToPrint(Parent *p) {
p->printP();
}
void howToPrint2(Parent &p) {
p.printP();
}
void main_3() {
Parent p;
Child c;
p.printP();
c.printC();
Parent * base = NULL;
base = &c;
base->printC();//有错,不能访问子类中的成员函数
//可以把子类对象赋给基类指针
//子类是一种特殊的父类
base->printP();
//子类是一种特殊的父类,可以子类当父类用
Parent &myp = c;
myp.printP();
cout << endl;
//测试父类指针,做函数参数
howToPrint(&p);
howToPrint(&c);
//测试引用
howToPrint2(p);
howToPrint2(c);
//可以用子类对象来初始化父类对象
//父类
//编译器提供的行为
Parent p3 = c;
}
}
继承中的构造析构调用原则:
1、子类对象在创建时会首先调用父类的构造函数,记得初始化父类带参构造函数
2、父类构造函数在执行结束后,执行子类的构造函数
3、当父类的构造函数有参数时,需要在子类的初始化列表中显示调用
4、析构函数再用的先后顺序和构造函数相反。
原则:
先构造父类,再构造成员变量、最后析构自己
先析构自己,再析构成员变量、最后析构父类
记住:先构造的对象,后释放。
没有父类哪有子类,先调用父类构造函数
在子类对象构造时,需要调用父类构造函数对其继承得来的成员进行初始化
在子类对象析构时,需要调用父类析构函数对其继承得来的成员进行清理
继承中的同名函数和变量,显示调用
using namespace std;
class Parent {
public:
int a;
int b;
void print() {
printf("father--->b:%d\n", b);
}
protected:
private:
};
class Child :public Parent {
public:
int b;
int c;
void print() {
printf("son--->b:%d\n", b);
}
protected:
private:
};
void main_5() {
Child b1;
b1.b = 10;
b1.Parent::b = 2;//要调用父类的b,需要加上Parent
b1.print();
b1.Parent::print();
}
继承中的static
记得在类外要初始化,不仅仅是初始化,也是分配内存的意思。
namespace staic {
class A {
public:
//单例的时候才设置成私有的
A() {
//cout<<a<<endl;
}
public:
static int a;
int b;
void print() {
printf("father--->b:%d\n", b);
printf("father--->a:%d\n", a);
}
protected:
private:
};
int A::a = 10;//不仅仅是初始化,还要告诉c++编译器,分配内存
class B :private A {
public:
//int b;
int c;
void print() {
printf("son---@b:%d\n", b);
printf("son---->a%d\n", a);
}
protected:
private:
};
}
using namespace staic;
void main() {
A a;
B b;
b.print();
}
多重继承
Java中支持单继承,C++支持多继承,这是历史遗留问题,C++出现的比较早,Java出现的比较晚,Java支持接口的多继承。
C++多继承完全可以通过,单继承来实现,而且多继承带来的复杂性,远远大于它的方便性。所以开发中一般使用多继承。
多继承中的二义性
class A{
public:
int i;
};
class B1: virtual public A{
public:
};
class B2:virtual public A{
public:
};
class C:public B1,public B2{
public:
int get(){
return i;//这里会出现,i不明确。通过加virtual关键字来解决
}
}
通过虚继承来解决。