1.继承
继承的实质就是父类的数据子类成员中有一份
继承方式只会增强父类在子类中的权限显示
任何方式的继承子类都不能直接访问父类的私有属性,但可以通过父类留下的公有接口访问数据
#include<iostream>
#include<string>
using namespace std;
class Fox
{
public:
Fox(string name,int money):name(name),money(money) {}//构造函数
int& retunmoney()
{
return this->money;
}
void print()
{
cout << name << money << endl;
}
protected:
string name;
private:
int money;
};
class Son :public Fox //公有继承
{
public:
void print()
{
//cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
cout <<name<< endl;
}
protected:
private:
};
class Son1 :protected Fox //保护继承
{
public:
void print()
{
//cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
cout << name << endl;
cout << Fox::retunmoney() << endl;//可以通过父类留下的公有接口访问父类的私有属性
}
protected:
};
class Son2:private Fox //私有继承
{
public:
void print()
{
//cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
cout << name << endl;
}
protected:
};
int main()
{
while (1);
return 0;
}
1.2 关于继承的权限问题:任何继承方式都不可以访问父类的私有属性
继承后属性提升问题 | |||
---|---|---|---|
protected继承 | protected | protected | 不可直接访问 |
public继承 | public | protected | 不可直接访问 |
private继承 | private | private | 不可直接访问 |
知识点:当子类用私有继承父类属性后 会导致父类中的保护属性变成子类的私有属性
子类是可以访问该私有属性,但是通过子类再次继承子类之后(我们称为孙子类)
会导致孙子类无法访问任何一个属性
#include<iostream>
#include<string>
using namespace std;
class Fox
{
public:
Fox(string name,int money):name(name),money(money) {}//构造函数
int& retunmoney()
{
return this->money;
}
void print()
{
cout << name << money << endl;
}
protected:
string name;
private:
int money;
};
class Son :public Fox //公有继承
{
public:
void print()
{
//cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
cout <<name<< endl;
}
protected:
private:
};
class Son1 :protected Fox //保护继承
{
public:
void print()
{
//cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
cout << name << endl;
cout << Fox::retunmoney() << endl;//可以通过父类留下的公有接口访问父类的私有属性
}
protected:
};
class Son2:private Fox //私有继承
{
public:
void print()
{
//cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
cout << name << endl;
}
protected:
};
class Grandson :public Son2 //继承私有继承的子类
{
void print()
{
// cout << name << endl;//上一个子类中所有属性都为私有属性,当前类无法访问任何一个数据
}
2.继承中构造函数的写法
父类的数据必须由父类的构造函数初始化
子类中构造函数,必须调用父类自己的构造函数,并且使用参数列表的方式(这里指的是构造父类的情况),自己的属性初始化随便写
单继承和多继承
单继承:只有一个父类
多继承:两个或以上的父类
单继承
#include<iostream>
#include<string>
using namespace std;
class Fox
{
public:
Fox(string name,int money):Fname(name),money(money) {}//构造函数
int& retunmoney()
{
return this->money;
}
void print()
{
cout << Fname << money << endl;
}
protected:
string Fname;
private:
int money;
};
class Son :public Fox //公有继承
{
public:
void print()
{
//cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
cout <<Fname<< endl;
}
Son(string Fname, int money, int Sname, int sonmoeny) :Fox(Fname, money) //利用参数初始化列表初始化父类构造函数
{ //子类初始话方式随便
this->Sname = Sname;
this->sonmoney = sonmoeny;
}
protected:
string Sname;
private:
int sonmoney;
};
class Son1:protected Fox //保护继承
{
public:
Son1(string Fname,int money,string Sname,int sonmoeny) :Fox(Fname, money) //利用参数初始化列表初始化父类构造函数
{ //子类初始话方式随便
this->Sname = Sname;
this->sonmoney = sonmoeny;
}
void print()
{
//cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
//cout << Fname << endl;
//cout << Fox::retunmoney() << endl;//可以通过父类留下的公有接口访问父类的私有属性
cout << Sname << sonmoney << endl;
cout << Fname << Fox::retunmoney() << endl;
}
protected:
string Sname;
private:
int sonmoney;
};
class Son2:private Fox //私有继承
{
public:
void print()
{
//cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
cout << Fname << endl;
}
protected:
};
class Grandson :public Son2 //继承私有继承的子类
{
void print()
{
// cout << name << endl;//上一个子类中所有属性都为保护属性,当前类无法访问任何一个数据
}
};
int main()
{
Son1 Foxson("狐狸",18,"狐狸儿子",0);
Foxson.print();
return 0;
}
多继承:
#include<iostream>
#include<string>
using namespace std;
class FoxM
{
public:
FoxM(string name, int age) :Mname(name), Mage(age) {}
protected:
string Mname;
int Mage;
};
class FoxF
{
public:
FoxF(string name, int age) :Fname(name), Fage(age) {}
protected:
string Fname;
int Fage;
};
class FoxSon :public FoxM, public FoxF //多继承
{
public:
FoxSon(string Mname, int Mage, string Fname, int Fage)
:FoxF(Mname, Mage), FoxM( Fname,Fage)//初始化参数列表
{
this->SonName = "小狐狸";
this->Sonage = 18;
}
void pring()
{
cout << Mname << Mage << endl;
cout << Fname << Fage << endl;
cout << SonName << Sonage << endl;
}
protected:
string SonName;
int Sonage;
};
int main()
{
FoxSon fox1("母狐狸",15,"大狐狸",12);
fox1.pring();
return 0;
}
3.关于继承中同名的问题
-
数据成员同名
-
成员函数名同名
-
正常赋值调用
-
#include<iostream> #include<string> using namespace std; class Fox1 { public: Fox1(string name,int age):name(name),age(age) {} void printf() { cout << name << age<<endl; } protected: string name; int age; }; class Fox2 :public Fox1 { public: Fox2(string name, int age) :Fox1(name, age) { this->name = "狐狸"; this->age = 3; } void printf() { cout << name << age << endl;//就近原则 在继承中 出现同名行为或者数据 都是就近原则 Fox1::printf();//可以使用类名限定的方式去访问 cout << Fox1::name << Fox1::age << endl;//可以使用类名限定的方式去访问 } protected: string name; int age; }; int main() { Fox2* pFox2 =new Fox2("狐狸123",5); pFox2->printf();//优先调用自己子类中的同名函数 pFox2->Fox1::printf();//通过类名限定调用父类中的同名函数 return 0; }
-
非正常赋值调用
-
允许子类对象填充父类指针
-
int main() { //非正常调用 Fox1* PFox1 = new Fox2("狐狸",3); PFox1->printf();//优先调用指针类型的函数,也就是调用父类中的成员函数 return 0; }
菱形构造的问题
-
所谓菱形构造问题就是 一个父类产生单独的两个子类,都继承了父类的数据成员
-
当两个子类又再次多继承出来一个子类 会导致构造函数中出现相同的数据成员
-
virtual关键字避免了该情况的发生,用virtual修饰子类,出现菱形继承时,默认使用最构造父类的构造函数初始父类中的数据成员,有效的避免了产生相同的数据成员问题
-
#include<iostream> #include<string> using namespace std; //继承的属性一致都存在 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(100, 200), C(300, 400), A(1011) { } void printf1()//A为1011 使用最开始父类的值 { //只有一个a 只有一份 cout << a << endl; cout << B::a << endl; cout << C::a << endl; printC(); } protected: };
析构问题
-
构造顺序和参数初始化列表的顺序无关,构造顺序和继承顺序一致
-
析构是反过来的
#include<iostream> #include<string> #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"; } }; int main() { { B b; //ABBA } cout << endl; F f;//C A D F F D A C // return 0; }
作业:
-
实现形状类的继承
-
#include<iostream> #include<string> using namespace std; class Shape { public:Shape(string form="",double length = 0.0, double breadth = 0.0, double radius = 0.0) {}//缺省方式 protected: double length;//长度 double breadth;//宽度 double radius;//半径 string form;//形状 }; class Rect :public Shape { public: Rect(string form, double radius, double breadth=0.0, double length=0.0) :Shape(form, length, breadth, radius) { this->perimeter = radius * 2 * 3.14; this->area = 3.14 * radius * radius; } void printf() { cout << "形状是" << "\t" << Shape::form << "面积是" << area << "周长是" << perimeter; } private: double perimeter; double area; }; class Circle :public Shape { public: Circle(string form, double radius=0.0, double breadth = 0.0, double length = 0.0) :Shape(form, radius, breadth, length) { this->perimeter = (breadth + length) * 2; this->area = breadth * length; } void printf() { cout << "形状是" << "\t" << Shape::form << "面积是" << area << "周长是" << perimeter; } private: double perimeter; double area; }; int main() { Rect testpact("圆形", 5); testpact.printf(); Circle testcircle("长方形",0.0,5,10); testcircle.printf(); return 0; }
作业2:多名老师为父类的研究生类:
#include<iostream>
#include<string>
using namespace std;
class Teacher
{
public:Teacher(string name):Tname(name)
{
}
protected:
string Tname;
};
class Student
{
public:Student(string Sname) :Sname(Sname) {}
protected:
string Sname;
};
class Graduate:public Teacher, Student//继承老师类和学生类
{
public:
Graduate(string Sname, string Tname) :Teacher(Tname), Student(Sname) {}
void printf()
{
cout << "该研究生名:" << Sname << "\t" << "老师名" << Tname << endl;
}
protected:
};
int main()
{
Graduate fox("小狐狸", "莫大帅");
fox.printf();
return 0;
}