当前位置:   article > 正文

day7 C++继承与派生 权限控制 类的设计_继承权限设计

继承权限设计

定义

从已有的类产生新的类叫派生,新的类叫子类(派生类),已有类叫父类(基类),
称子类继承父类;或父类派生出子类。派生与继承是同一种意义的两种表述。
  • 1
  • 2

作用

C++利用继承来实现代码的可重用。子类继承父类的全部成员(除了构造函数与析构函数);
则子类对象可以调用父类的函数而不必重新定义函数与变量。
  • 1
  • 2

继承的关系定性

is a

is a 的关系是一种属于的关系,如:学生是人,老师是人。校长是人。则可以把 
人设计成为基类把学生,老师,校长设计成为派生类。
  • 1
  • 2

has a

has a 的关系是一种拥有关系,如:电脑有: CPU,硬盘,显卡,内存等等。则可以
设计 CPU 硬盘 显卡 内存 等等为基类。电脑为派生类,由各种组件组成。
  • 1
  • 2

语法

派生类:

class  派生类名 :继承方式 基类名
{
正常声明;
}
  • 1
  • 2
  • 3
  • 4

继承示例

基类 man
class man{
char* sex;
int tall;
char *name;
public:
    void showData(char _name[],char _sex[],int _tall){
        sex=new char[strlen(_sex)+1];
        strcpy(sex,_sex);
        tall=_tall;
        name=new char[strlen(_name)+1];
        strcpy(name,_name);
        cout<<"名字:"<<name<<" 性别:"<<sex<<" 身高:"<<tall<<endl;
    }

};
派生类 student
class student:public man
{

};
int main() {
    student st;
    st.showData("小明","男",180);
    return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
如果需要实现老师类,校长类,则不需要重复实现函数 showdata(),都继承至父类就好了
  • 1

继承方式

示例说明:
存在以下基类

class base{
public:
	int pub;
protected:
	int pro;
private:
	int pri;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

派生类在不同方式继承下,三个数据的可见性表:

继承方式publicprotectedprivate
pubpublicprotectedprivate
proprotectedprotectedprivate
pri不可见不可见不可见

补充说明

类内的权限控制:

publicprotectedprivate
对外开放子类可见仅本类内

派生类的构造

基类成员初始化

派生类要调用基类成员必须对基类进行构造
基类成员的初始化还是由基类的构造函数完成。然后再执行子类构造。
  • 1
  • 2

语法:

派生类名::派生类名(参数总表)
:基类名(参数表),内嵌子对象(参数表)
{
派生类新增成员的初始化语句; //也可出现地参数列表中
}
  • 1
  • 2
  • 3
  • 4
  • 5

需要注意的是:在C++类的模块中系统提供很多默认的东西。这里也不例外。当你都不实现采用系统提供的构造函数时,不需要显式调用基类构造函数。但如果父类没有默认构造函数;则需要上面的格式实现派生类构造器。

构造顺序与析构顺序

构造顺序:

派生类的构造,会先调用基类的构造,如果派生类的数据中存在其他类对象作为数据成员
则构造顺序为:基类构造->派生类内数据对象构造->派生类构造
  • 1
  • 2

** **:当派生类构造完成则该派生类对象已经全部初始化,所以基类与类内对象必须提前
初始化。

析构顺序:

析构顺序为:派生类析构->派生类内数据对象析构->基类析构
  • 1

个人理解:当变量的存在空间销毁时自动回收,则当派生类对象析构时,带动其他两个析构。
例子:

class birthday{
public:
	birthday(){
		cout<<birthday<<endl;
	}
	~birthday(){
        cout<<"~birthday()"<<endl;
    }
}
class man{
public:
    man(){
        cout<<"man()"<<endl;
    }
    ~man(){
        cout<<"~man()"<<endl;
   }
};

class student:public man
{   public:
    student(){
        cout<<"student()"<<endl;
    }
   ~student(){
        cout<<"student()"<<endl;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

测试:

int main() {
    student st;
    //st.showData("小明","男",180);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5

结果:
在这里插入图片描述

继承中的拷贝构造

派生类中的默认拷贝构造器会调用父类中默认或自实现拷贝构造器,若派生类中自实现拷
贝构造器,则必须显示的调用父类的拷贝构造器

自实现使用格式可参考以下实例
  • 1

示例

class Student{
public:
	Student(const Student & another)
	{
		name = another.name;
		num = another.num;
		sex = another.sex;
}
}
class Graduate{
	Graduate(const Graduate & another)
	:Student(another),salary(another.salary){ }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这里之所以可以直接传派生类对象给基类拷贝构造函数,是因为继承有个赋值兼容的机制

赋值兼容

赋值兼容是指可以派生类对象可以隐式转换为基类对象,这一点在拷贝构造,友元中都有相关应用。

继承中的赋值运算符重载

在继承中,编译器都会提供 派生类与基类的默认赋值运算符重载,关于默认可参考day4 C++复制构造、赋值运算符重载、this指针,类对象内存,赋值运算符重载跟普通成员函数一样都可以被继承,同时,系统提供的默认会自动调用基类的赋值运算符重载,但如果自实现了派生类的赋值运算符重载,则需要主动显式地调用基类重载。

自实现使用格式可参考以下实例
  • 1

示例

class student{
private:
	string name;
	int num;
	char sex;
public:
	student& opreator=(const student& another){
		if(this == &another)
			return *this;
		this->name = another.name;
		this->num = another.num;
		this->sex = another.sex;
		return * this;
	}

}
class Graduate{
private:
	int salary;
public:
Graduate & operator=(const Graduate & another){
	if(this == &another)
		return *this;
	Student::operator =(another);
	this->salary = another.salary;
	return * this;
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

友元

友元并不能继承,但是有些时候需要使用基类的友元。这时候可以借助赋值兼容把子类对象强转成为基类对象。

shadow现象

shadow现象是指派生类对象中出现了与基类的同名函数,注意这里单单是因为同名派生类隐藏基类的同名成员。如果需要访问这些被隐藏的成员,需要加上基类名作用域。

格式:基类名::成员名;
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/106002?site
推荐阅读
相关标签
  

闽ICP备14008679号