第8节 C++继承和派生
继承方式与权限问题
继承的写法
//父类 基类
class parent
{
};
//子类 派生类
//公有继承
class soon1:public parent
{
public:
protected:
};
//保护继承
class son2:protected parent
{
public:
protected:
};
//私有继承
class son3:private parent
{
public:
protected:
};
//继承和派生
//继承:子类中没有产生新的属性和行为
//派生:派生类中有新的属性和行为产生
class 子类名:继承方式 父类名
{
};
//继承方式 就是权限限定词
继承实质与权限问题
- 继承的实质:父类的数据和成员子类中有一份
- 权限问题:继承方式只会增强父类属性在子类中的权限显示
public | protected | private | |
---|---|---|---|
public继承 | public | protected | 不可直接访问 |
protected继承 | protected | protected | 不可直接访问 |
private继承 | private | protected | 不可直接访问 |
#include<iostream>
#include<string>
using namespace std;
class parent
{
public:
void print()
{
cout << name << "\t" << money << endl;
}
string& getWide()
{
return wide;
}
protected:
string name;
int money;
private:
string wife;
};
//子类
class son :public parent
{
public:
void printSon()
{
print();
cout << name<<"\t"<<money<< endl;
//cout << wife << endl;父类中的私有属性不能直接访问
cout << getWide() <<endl;//间接通过父类的函数访问
}
protected:
};
class A
{
public:
int a1;
protected:
int a2;
private:
int a3;
};
class B :public A
{
public:
//int a1;
protected:
//int a2;
private:
//int a3;不能直接访问
};
class C :protected A
{
public:
protected:
//int a1; public 显示protected
//int a2;
private:
//int a3;不能直接访问
};
class D :private A
{
public:
void print()
{
cout << a1 << endl;;
cout << a2<< endl;
}
protected:
private:
//int a1; public 显示protected
//int a2;
//int a3;//父类的私有属性不能直接访问
};
//私有继承会导致当前父类 无法在孙子类有任何作用
class F :public D
{
public:
};
int main()
{
son boy;
boy.printSon();
B b;
b.a1 = 123;
C c;
//c.a1 = 12;
return 0;
}
继承中的构造函数
- 父类的属性通过父类的构造函数初始化
- 子类中的构造函数,必须要调用父类构造函数,必须采用初始化参数列表的方式
#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 = sonFName;
this->sonSName = sonFName;
}
void print()
{
cout << "父:" << FName + SName << endl;
cout << "子:" << sonFName + sonSName << endl;;
}
protected:
string sonFName;
string sonSName;
//string FName;
//string SName;
};
int main()
{
Son son;//子类构造对象,优先调用父类构造函数
Son son1("白","老鬼","日天");
return 0;
}
单继承和多继承
- 单继承:只有一个父类
- 多继承:两个或者两个以上的父类、
- 继承的属性一直都存在,无论被继承多少次,所以类一般不会被继承很多层,会导致类的臃肿
#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 = sonFName;
this->sonSName = sonFName;
}
void print()
{
cout << "父:" << FName + SName << endl;
cout << "子:" << sonFName + sonSName << endl;;
}
protected:
string sonFName;
string sonSName;
//string FName;
//string SName;
};
//多继承
//欧田
//阳子
//欧阳田子
class MM
{
public:
//MM() = default;
MM(string mmFName, string mmSName)
{
this->mmFName = mmFName;
this->mmSName = mmSName;
}
protected:
string mmFName;
string mmSName;
};
class GG
{
public:
//GG() = default;
GG(string ggFName, string ggSName)
{
this->ggFName = ggFName;
this->ggSName = ggSName;
}
protected:
string ggFName;
string ggSName;
};
class Girl:public GG,public MM
{
public:
//子类想要这种构造函数,每个父类都要有一个无参的构造函数
//Girl(){}
Girl(string mmFName, string mmSName, string ggFName, string ggSName)
:MM(mmFName, mmSName), GG(ggFName,ggSName)
{
girlFName = ggFName + mmFName;
girlSName = ggSName + 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();
Girl girl("阳", "子", "欧","田");
girl.print();
return 0;
}
继承中同名问题
- 数据成员同名
- 成员函数同名
- 正常调用
- 非正常赋值调用
#include <iostream>
#include<string>
using namespace std;
class MM
{
public:
MM(string name, int age) :name(name), age(age){}
void print()
{
cout << "MM:";
cout << name << "\t" << age << endl;
}
protected:
string name;
int age;
};
class Girl :public MM
{
public:
Girl(string name, int age) :MM("父类", 28), name(name), age(age){}
void print()
{
//不做特别处理,就近原则
cout << name << "" << age << endl;
//类名限定
cout << MM::name << "\t" << MM::age << endl;
MM::print();
}
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){}
void printC()
{
cout << a << endl;
}
protected:
int c;
};
class D :public C, public B
{
public:
//菱形继承,必须调用祖父的构造函数
D() :B(1, 2), C(3, 4),A(999)
{
}
void print()
{
//只有一个a 只有一份
cout << a << endl;
cout << B::a << endl;
cout << C::a << endl;
printC();
}
protected:
};
int main()
{
//不做特别处理,就近原则
//正常对象调用
Girl girl("girl", 18);
girl.print();
MM mm("mm", 28);
mm.print();
//正常的指针调用
//就近原则
Girl* pG = new Girl("newGirl", 19);
pG->print();
pG->MM::print();
MM* pM = new MM("newMM", 29);
pM->print();
//非正常的指针
//允许子类对象初始化父类指针
MM* pMM = new Girl("newGilr", 49);
pMM->print();//父类的
//在没有virtual 情况下,看指针类型
//在有virtual情况,看赋值对象
//父类对象初始化子类指针,不安全
//Girl *pGirl = new MM("newMM",29);错误
//Girl* pGirl = (Girl*)pM;
//pGirl->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"; } }; class C { public: C(){ cout << "C"; } ~C(){ cout << "C"; } }; class D { public: D(){ cout << "D"; } ~D(){ cout << "D"; } }; //构造顺序和继承顺序一致 class F :public C, public A, public D { public: //任何构造顺序问题,都和初始化参数列表无关 F(){ cout << "F"; } ~F(){ cout << "F"; } }; //CADF FDAC int main() { { B b;//ABBA } cout << endl; F f; return 0; }