C++面向对象编程 继承
一、 面向对象编程中的一些重要名词解释:
1.类:
①是一组具有相同属性和行为的对象的抽象。
②类不是一个实体的存在,例如人类这个类别,学生不是一个实体的存在,而学生中的的姓名,性别,年龄,学号………才是这个类别中的实体,学生并不是。类只是一个模子,确定对象将会有的特征(属性)和行为(方法);
③类是面向对象程序设计方法的核心,利用类可以实现对数据的封装和隐藏。
④在面向对象程序设计中,程序模块是由类构成的。类是对逻辑上相关的函数与数据的封装,它是对问题的抽象描述
2.封装:
①是面向对象思想中最基础的概念,实质上是将相关的函数和对象放一起,对外有函数作为操作通道,对内则以变量作为操作原料。
②封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的函数代码进行有机地结合,形成”类“,其中数据和函数都是类的成员
3.继承:
①继承机制是面向对象程序设计使代码可以复用的最重要的手段
②它允许程序员在保持原有的特性基础上进行扩展,增强功能。这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。
③继承就像是如基类为人,派生类为士兵、工人。基类人有很多特性,如名字、年龄。派生类继承了基类中的特性,派生类士兵、工人,同样也有名字、年龄和其他标识。
④继承分为public 公有继承、protected 保护继承、provated私有继承。
了解了上述这些基本的概念我们不妨通过编程学习来加深对这些名词的理解
二、编程学习继承的用法及其访问权限测试
1.继承访问权限测试:
(一)设计类A,让它具有public,protected,private等不同的成员函数或变量,再通过main函数测试是否都能访问到。
创建一个Person类,其中m_Name为公有成员,m_Sex为保护成员,m_Age 为私有成员。
class Person {
public://公共权限
string m_Name;
protected://保护权限
string m_Sex;
private://私有权限
int m_Age;
};
main函数测试三种属性的访问权限
int main()
{
Person p;
p.m_Name = "林一";
p.m_Sex = "male";
p.m_Age = 20;
cout << "\t\t||";
cout << "===============Person类===============" << endl;
cout << "\t\t||\n\t\t||";
cout << "姓名:" << p.m_Name << " 年龄:" << p.m_Age << " 性别:" << p.m_Sex<< endl;
cout << "\t\t||";
cout << "======================================" << endl;
return 0;
}
执行main函数可以发现程序编译失败,并出现下图的报错,说明只有public里的成员可以在类外访问,而protected,private里的成员在类外没有被访问的权限。
根据上面的实验结果对以上代码进行如下修改:
class Person {
public://公共权限,类内可以访问,类外也可以访问
string m_Name;
double getAge() {
m_Age = 20;
return m_Age;
}
string getSex() {
m_Sex = "male";
return m_Sex;
}
protected://保护权限,类内可以访问,类外不可以访问
string m_Sex;
private://私有权限,类内可以访问,类外不可以访问
int m_Age;
};
int main()
{
Person p;
p.m_Name = "林一";
p.getSex();
p.getAge();
cout << "===============Person类===============" << endl;
cout << "\n";
cout << "姓名:" << p.m_Name << " 年龄:" << p.getAge() << " 性别:" << p.getSex()<< endl;
cout << "\n";
cout << "======================================" << endl;
return 0;
}
因为public成员是对所有用户开放的,所有用户都能直接调用,能让类外访问;
而protected和private只对内部类开放访问,protected和private都可以被本类中的成员函数访问,外部类不能直接访问。
因此我们可以在内部类中的public里创建函数用来获取protected和private的成员。
这样一来用户可以通过调用public中的函数继而获取到protected和private的成员。
(二)类B通过public,protected,private等不同方式继承A,在类B的成员函数中测试访问A的成员函数或变量;在类B中添加public,protected,private等不同属性的成员函数或变量,在外部测试访问B的各个成员函数或变量
①class A public B:
class Pub_Student :public Person //public继承
{
public:
void Test() {
m_Name = "林二";
m_Sex = "female";
// m_Age = 20;//不可访问
}
int pub_pub_grade1;
protected:
int pub_pro_grade2;
private:
int pub_pri_grade3;
};
int main()
{
Pub_Student s1;
s1.pub_pub_grade1 = 100;
// s1.pub_pro_grade2;//不可访问
// s1.pub_pri_grade3;//不可访问
s1.m_Name="林二";
// s1.m_Sex;//不可访问
// s1.m_Age;//不可访问
cout << "==========Student类 public继承==========" << endl;
cout << "\n";
cout << "姓名:" << s1.m_Name << " 性别:" << " 成绩:" << s1.pub_pub_grade1 << endl;
cout << "\n";
cout << "========================================" << endl;
return 0;
}
从实验中可以看出通过public方式继承类Person的类Pub_Student,其能够在自己类的内部访问到基类(Person类)的public与protected成员;
而在类外中只能访问到基类的public以及自己类的public成员。
②class A protected B:
class Pro_Student :protected Person //public继承
{
public:
void Test() {
m_Name = "林三";
m_Sex = "male";
// m_Age = 20;//不可访问
}
int pro_pub_grade1;
protected:
int pro_pro_grade2;
private:
int pro_pri_grade3;
};
int main()
{
Pro_Student s2;
s2.pro_pub_grade1 = 150;
// s2.pro_pro_grade2;//不可访问
// s2.pro_pri_grade3;//不可访问
// s2.m_Name;//不可访问
// s2.m_Sex;//不可访问
// s2.m_Age;//不可访问
cout << "========Student类 protected继承========" << endl;
cout << "\n";
cout << "姓名:"<< " 性别:" << " 成绩:" << s2.pro_pub_grade1 << endl;
cout << "\n";
cout << "=======================================" << endl;
return 0;
}
从实验中可以看出通过protected方式继承类Person的类Pro_Student,其能够在自己类的内部访问到基类(Person类)的public与protected成员,但在类外中只能访问到自己类的public成员。
而因为派生类(Pro_Student类)是通过protected方式继承基类(Person类),所以导致基类Person中的public成员在派生类中成为了protected成员,进而无法进行访问。
③class A private B:
class Pri_Student :private Person //public继承
{
public:
void Test() {
m_Name = "林四";
m_Sex = "female";
// m_Age = 20;//不可访问
}
int pri_pub_grade1;
protected:
int pri_pro_grade2;
private:
int pri_pri_grade3;
};
int main()
{
Pri_Student s3;
s3.pri_pub_grade1 = 200;
// s3.pro_pro_grade2;//不可访问
// s3.pro_pri_grade3;//不可访问
// s3.m_Name;//不可访问
// s3.m_Sex;//不可访问
// s3.m_Age;//不可访问
cout << "=========Student类 private继承=========" << endl;
cout << "\n";
cout << "姓名:" << " 性别:" << " 成绩:" << s3.pri_pub_grade1 << endl;
cout << "\n";
cout << "=======================================" << endl;
return 0;
}
从实验中可以看出通过private方式继承类Person的类Pri_Student,其能够在自己类的内部访问到基类(Person类)的public与protected成员,但在类外中只能访问到自己类的public成员。
而因为派生类(Pri_Student类)是通过private方式继承基类(Person类),所以导致基类Person中的public成员在派生类中成为了private成员,进而无法进行访问。
总结:
(三)B以private方式继承A,尝试把A中的部分public成员提升为public
class newPri_Student :private Person
{
public:
void Test() {
m_Name = "林五";
m_Sex = "male";
//m_Age = 20;//不可访问
}
int pri_pub_grade1;
using Person::m_Name;
using Person::m_Sex;
protected:
int pri_pro_grade2;
private:
int pri_pri_grade3;
};
int main()
{
newPri_Student s4;
s4.pri_pub_grade1 = 200;
// s4.pro_pro_grade2;//不可访问
// s4.pro_pri_grade3;//不可访问
s4.m_Name = "林五";
s4.m_Sex = "male";
// s4.m_Age;//不可访问
cout << "=========Student类 private继承=========" << endl;
cout << "\n";
cout << "姓名:" << s4.m_Name << " 性别:" << s4.m_Sex <<" 成绩:" << s4.pri_pub_grade1 << endl;
cout << "\n";
cout << "=======================================" << endl;
return 0;
}
Student以private方式继承Person,可以用{using Person::m_Name; }
把Person中的部分public成员例如m_Name提升为public。
2.友元类继承测试:
(一)设计类A含有私有变量a,在类A中友元给类C
class A {
private:
int _a;
friend class C;
};
(二)设计类B继承A,添加私有变量b;在类C中测试访问类B的成员变量a,b
class B :public A {
private:
int _b;
};
class C {
public:
void Test() {
B b;
b._a;
b._b;//不可访问
}
};
可以看出在类C中可以访问B的成员变量_a,无法访问_b。
因为类C被说明为类A的友元,类C的所有成员函数都成为类A的友元函数,这就意味着作为友元类C中的所有成员函数都可以访问类A中的所有成员(包括私有成员)。
(三)设计类D继承C,在D的成员函数中测试访问类A的成员变量a,类B的成员变量a, b。
class D :public C{
public:
void Test() {
A a;
B b1;
a._a;//不可访问
b1._a;//不可访问
b1._b;//不可访问
}
};
可以看出在类D中,对于类A的成员变量_a,类B的成员变量_a,_b都不可访问。
总结:
①友元关系是单向的,不具有交换性。
②友元关系也不具有传递性。
③友元关系不能被继承,基类的友元类未必是子类的友元,某类型的友元的子类未必是该类型的友元。