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;
}
|