C++继承和派生
## 继承方式与权限问题
+ 继承的写法
```c++
//父类 基类
class parent
{
};
//子类 派生类
//公有继承
class son1:public parent
{
public:
protected:
};
//保护继承
class son2:protected parent
{
public:
protected:
};
//私有继承
class son3:private parent
{
public:
protected:
};
//继承和派生
//继承: 子类中没有产生新的属性或者行为
//派生: 派生类中有新的属性和行为产生
class 子类名:继承方式 父类名
{
};
//继承方式 就是权限限定词
```
+ 继承实质与权限问题
+ 继承的实质: 父类的数据和成员子类中有一份
+ 权限问题: 继承方式只会增强父类属性在子类中的权限显示
| | public | protected | private |
| ------------- | --------- | -------- - | ------------ |
| protected继承 | protected | protected | 不可直接访问 |
| public继承 | public | protected | 不可直接访问 |
| private继承 | private | private | 不可直接访问 |
继承中的构造函数
父类的属性通过父类的构造函数初始化
子类中的构造函数,必须要调用父类构造函数,必须采用初始化参数里列表的方式
单继承和多继承
单继承:只有一个父类
多继承:两个及两个以上的父类
继承的属性,无论被继承多少次都存在,所以类一般不会被继承很多层,会导致类的臃肿。
#include <iostream>
#include <string>
using namespace std;
class Parent
{
public:
Parent() { cout << "父类无参构造函数" << endl; }
Parent(string FName, string SName):FName(FName), SName(SName){}
protected:
string FName;
string SName;
};
//单继承
class Son :public Parent
{
public:
//这种写法,父类必须存在无参的构造函数,当然缺省也可以
Son() { cout << "子类无参构造函数" << endl; }
Son(string FName, string SName, string sonSName) :Parent(FName,SName)
{
//自己的属性用什么办法初始化都行
this->sonFName = FName;
this->sonSName = sonSName;
}
void print()
{
cout << "父:" << FName + SName << endl;
cout << "子:" << sonFName + sonSName << endl;
}
protected:
string sonFName;
string sonSName;
//string FName;
//string SName;
};
//多继承
//欧田
//阳子
//欧阳 田子
class Mother
{
public:
//Mother() = default;
Mother(string mmFName, string mmSName)
{
this->mmFName = mmFName;
this->mmSName = mmSName;
}
protected:
string mmFName;
string mmSName;
};
class Father
{
public:
//Father() = default;
Father(string ggFName, string ggSName)
{
this->ggFName = ggFName;
this->ggSName = ggSName;
}
protected:
string ggFName;
string ggSName;
};
class Baby :public Father,public Mother
{
public:
//子类想要这种构造函数,每个父类都要有一个无参的构造函数
//Girl() {}
Baby(string mmFName, string mmSName, string ggFName, string ggSName)
:Mother(mmFName,mmSName), Father(ggFName,ggSName)
{
/*
//欧田
//阳子
//欧阳 田子
*/
girlFName = Father::ggFName + Mother::mmFName; //欧阳
girlSName = Father::ggSName + Mother::mmSName; //田子
}
void print()
{
cout << "父:" << ggFName + ggSName << endl;
cout << "母:" << mmFName + mmSName << endl;
cout << "女:" << girlFName + girlSName << endl;
}
protected:
string girlFName;
string girlSName;
};
//继承的属性一致都存在
class A
{
public:
A(int a) :a(a) {}
int a;
};
class B:public A
{
public:
B(int a,int b) :A(a),b(b) {}
int b;
};
class C :public B
{
public:
C(int a, int b,int c) :B(a,b),c(c) {}
int c;
};
class D :public C
{
public:
D(int a, int b, int c,int d) :C(a,b,c), d(d) {}
int d;
};
int main()
{
Son son; //子类构造对象,优先调用父类构造函数
Son son1("白", "老鬼", "日天");
son1.print();
Baby baby("阳", "子", "欧", "田");
baby.print();
return 0;
}
构造函数中同名问题
数据成员同名
成员函数同名
#include<iostream>
using namespace std;
class Girl {
public:
Girl(string name,int age):name(name),age(age){}
//无论是成员函数还是数据成员不做特殊处理都是就近原则
void print() {
cout << "父类中的" << endl;
cout << name << "\t" << age << endl;
}
protected:
string name;
int age;
};
class Baby :public Girl {
public:
Baby(string name,int age):Girl("父类",28),name(name),age(age){}
void print() {
cout << name << " " << age << endl;//同名时,不做特别处理,就近原则,调用子类的
//远的用类名限定
cout << Girl::name << " " << Girl::age << endl;
//this指针标志的也是就近原则
}
protected:
string name;
int age;
};
//虚继承(菱形继承)
class A {
public:
A(int a) :a(a){}
protected:
int a;
};
class B :virtual public A {
public:
B(int a,int b):A(a),b(b){}
protected:
int b;
};
class C :virtual public A {
public:
C(int a, int c) :A(a), c(c){}
protected:
int c;
};
class D :public B, public C {
public://菱形继承必须调用祖父的构造函数
D() :B(1, 2), C(3, 4),A(999) {
}
void print() {
//结果都一样,只有一份的含义
cout << a << endl;
cout << B::a << endl;
cout << C::a << endl;
}
protected:
};
int main() {
//正常对象调用
Baby baby("女孩", 18);
baby.print();
//正常指针调用
Girl* pGirl = new Girl("newGirl", 19);
pGirl->print();
Baby* pBaby = new Baby("newBaby", 1);
pBaby->print();
pBaby->Girl::print();
//非正常指针
//允许子类对象初始化父类指针
Girl* pMM = new Baby("newGirl",28);
//调用父类的
pMM->print(); //在没有virtual的情况下,看指针类型;在有virtual的情况下看赋值对象
//父类对象初始化子类指针,不安全
//Baby* pBB = new Girl("newBaby", 10);
Baby* pBB = (Baby*)pMM;
pBB->print();//只能调用父类当中子类有的函数//但一般不被允许
D d;
d.print();
return 0;
}
构造和析构问题
单继承先构造父类的再构造子类的,析构顺序相反。
多继承
#include<iostream>
using namespace std;
class A {
public:
A() { cout << "A"; }
~A() { cout << "A"; }
protected:
};
class B :public A {
public:
B() { cout << "B"; }
~B() { cout << "B"; }
protected:
};
class C {
public:
C() { cout << "C"; }
~C() { cout << "C"; }
protected:
};
class D {
public:
D() { cout << "D"; }
~D() { cout << "D"; }
protected:
};
class E :public A, public C, public D {//构造顺序和初始化参数列表无关
//构造顺序和继承顺序一致ACDFFDA
public:
E() { cout << "E"; }
~E() { cout << "E"; }
};
int main() {
B b;
cout << endl;
E f;
return 0;
}