【C++ 语言】面向对象 ( 继承 | 重写 | 子类调用父类方法 | 静态多态 | 动态多态 | 虚函数 | 纯虚函数 )

举报
韩曙亮 发表于 2022/01/11 00:14:30 2022/01/11
【摘要】 文章目录 类的继承方法的重写子类中调用父类方法多态虚函数虚函数示例纯虚函数相关代码 类的继承 1. 继承表示 : C++ 中继承可以使用 “:” 符号 ,...



类的继承



1. 继承表示 : C++ 中继承可以使用 “:” 符号 , 格式为 "class 子类名称 : 父类名称{};"

//父类
class Parent{

};

//子类
//继承父类 Parent
class Child : Parent{

};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2. 继承作用域 : 继承可以指定作用域 , private , protected , public , 如果不写作用域 , 那么该继承就是默认私有继承 ; 作用域符号写在 冒号之后 , 父类名称之前 ;

3. 私有 ( private ) 继承 : 如果继承的作用域是私有的 ( private ) , 那么继承的所有的方法都是私有的 , Parent 中的 public 和 protected 方法会变成私有的 , 外部无法访问该方法 ;

4. C++ 多继承 : Java 中只能进行单继承 , 但是在 C++ 中是可以继承多个父类的 ; 在多继承时 , 使用 “,” 将多个父类分隔即可 ;

5. C++ 多继承作用域 : 多继承中 , 每个父类的作用域都可以单独指定;

#pragma once

//父类
class Parent{

public:
	void parent_method() {
	}

};

//父类
class Parent1{

public:
	void parent1_method() {
	}

};

//子类
//继承父类 Parent
//继承作用域 : 默认私有继承 private 
class  Child : private Parent, public Parent1{

};

  
 
  • 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


方法的重写



1. 子类重写父类方法 : 如果继承的两个父类有相同的方法 , 在子类冲又定义了一个相同的方法 , 这就是重写父类的方法 ;

#pragma once

using namespace std;

//父类
class Parent{
public:
	void parent_method() {
		cout << " Parent parent_method " << endl;
	}
};

//父类
class Parent1 {
public:
	void parent_method() {
		cout << " Parent1 parent_method " << endl;
	}

	void parent_method1() {
		cout << " Parent1 parent_method1 " << endl;
	}
};

//子类
//继承父类 Parent
//继承作用域 : 默认私有继承 private 
class Child : private Parent, public Parent1 {
public:
	void parent_method() {
		cout << " Child parent_method " << 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
  • 29
  • 30
  • 31
  • 32
  • 33

2.调用子类重写方法 : 调用子类重写的 “parent_method” 方法 , 其执行的是子类重写的方法 ;

3. 外部通过子类调用父类方法 : 如果调用的方法在子类中没有重写 , 那么调用的就是父类的方法 ;

	//在栈内存中创建一个 Child 对象, 并调用其重写的父类的方法
	Child child;
	//调用子类重写的父类的方法
	child.parent_method();

	//调用子类没有重写的父类方法
	child.parent_method1();

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4. 代码执行结果 : 调用子类重写后的方法 , 其调用的是子类的方法 , 如果调用子类没有重写的方法 , 那么调用的就是父类的方法 ;

 Child parent_method
 Parent1 parent_method1

  
 
  • 1
  • 2


子类中调用父类方法



1. 子类中调用父类的方法 : 使用 " 父类名称 :: 方法名() " 进行调用 , 该操作相当于 Java 中的 " super(); " 方法 ;

class Child : private Parent, public Parent1 {
public:
	void parent_method() {
		//子类中调用父类的方法 , 该操作相当于 Java 中的 super 方法 
		Parent::parent_method();
		Parent1::parent_method();

		cout << " Child parent_method " << endl;
	}
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2. 执行下面的代码 : 执行该子类实现的方法 , 该方法中先后调用了两个父类的方法 ;

	//在栈内存中创建一个 Child 对象, 并调用其重写的父类的方法
	Child child;
	//调用子类重写的父类的方法
	child.parent_method();

  
 
  • 1
  • 2
  • 3
  • 4

3. 代码执行结果 : 因为子类冲调用了父类的方法 , 因此两个父类的 parent_method 方法被先后执行了 ;

 Parent parent_method
 Parent1 parent_method
 Child parent_method

  
 
  • 1
  • 2
  • 3


多态



1. 多态 : 声明 Parent1 父类对象 , 为其赋值一个 Child 对象 , 此时调用其 parent_method 方法 , 调用的是父类的方法 ;

	//声明 Parent1 父类对象 , 为其赋值一个 Child 对象
	Parent1* parent1 = new Child();
	//此时调用其 parent_method 方法 , 调用的是父类的方法
	parent1->parent_method();

  
 
  • 1
  • 2
  • 3
  • 4

2. 执行结果 : 其调用的是 Parent1 父类中定义的 parent_method 方法 , 没有调用子类实现的方法 ;

 Parent1 parent_method

  
 
  • 1

如果必须要调用子类实现的方法 , 这里就需要用到虚函数 ;



虚函数



1 . 静态多态 : 在编译时 , 就可以确定函数调用的地址 ; 上面 多态 中的示例就是静态多态示例 ;

下面的虚函数的示例 , 是动态多态示例 ;

2 . 动态多态 : 在运行时 , 确定函数调用地址 , 这里就用到虚函数 ;

3 . 虚函数作用 : 让函数调用的地址 , 在运行时确定调用哪个函数 ;

4. 虚函数解析 : 在对象调用虚函数方法时 , 系统会查看该对象真正类型是什么类型 , 然后去调用对应类型的方法 ; 对象是使用什么类型的构造函数创建的 , 其真正的类型就是这个类型 , 因此最终调用该类中的虚函数方法 ;

5. 虚函数使用要点 :

  • 1. 构造方法 : 不能设置成虚函数, 如果将构造方法设置成虚函数 , 编译时会报错 ;
  • 2. 析构方法 : 必须设置成虚函数 , 释放子类对象内存时 , 必须释放子类对象的内存 , 否则子类对象的内存永远不会被释放 ;
  • 3. 没有子类 : 虚函数在子类继承父类时才有意义 , 根据类型动态判定该调用哪个方法 , 如果一个类没有子类 , 其设置成虚函数没有意义 , 但也不影响程序运行 ;


虚函数示例



虚函数代码示例解析 :

  • 1. 父类中定义虚函数 :
//父类
class Parent{
public:
	void parent_method() {
		cout << " Parent parent_method " << endl;
	}

	//虚函数
	virtual void virtual_method() {
		cout << " Parent virtual_method " << endl;
	}
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 2. 子类中重写虚函数 :
//子类
//继承父类 Parent
//继承作用域 : 默认私有继承 private 
class Child : public Parent, public Parent1 {
public:
	void parent_method() {
		//子类中调用父类的方法 , 该操作相当于 Java 中的 super 方法 
		Parent::parent_method();
		Parent1::parent_method();

		cout << " Child parent_method " << endl;
	}

	//重写父类的虚函数
	void virtual_method() {
		cout << " Child virtual_method " << endl;
	}
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 3. 调用虚函数 :
	//在栈内存中创建一个 Child 对象, 并调用其重写的父类的方法
	Child child;

	//多态

	//声明 Parent1 父类对象 , 为其赋值一个 Child 对象
	Parent* parent = new Child();

	//静态多态 : 在编译时 , 就可以确定函数调用的地址 ; 
	//	此时调用其 parent_method 方法 , 调用的是父类的方法
	parent->parent_method();

	//动态多态 : 在运行时 , 确定函数调用地址 , 
	//	此处调用的是子类实现的方法
	parent->virtual_method();

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 4. 代码执行结果 :
 Parent parent_method
 Child virtual_method

  
 
  • 1
  • 2
  • 5. 结果分析 :
    • ① 静态多态分析 : 第一次调用父类的 parent_method 方法 , 虽然子重写该方法 , 但是对象类型声明的是父类类型 , 其仍然调用父类方法 ;
    • ② 动态多态分析 : 第二次调用父类的 virtual_method 方法 , 该方法时虚函数 , 子类重写了该虚函数 , 在函数调用的时候 , 会自动根据对象的类型判定调用哪个方法 , 该对象使用 new Child() 创建 , 其类型是 Child 类型 , 因此最终调用的是子类重写的方法 ;


纯虚函数



1. 纯虚函数 : 类似于 Java 的抽象方法 , 父类中声明后 , 该方法必须实现 , 否则编译时报错 ;

2. 代码示例 :

① 父类中定义纯虚函数 :

//父类
class Parent{
public:
	//纯虚函数 , 类似于 Java 的抽象方法 , 
	//父类中声明后 , 该方法必须实现 , 否则编译时报错
	virtual void pure_virtual_method() = 0;
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

② 子类中实现虚函数 :

//子类
//继承父类 Parent
class Child : public Parent {
public:
	//实现纯虚函数方法 , 该方法必须实现 , 否则会报错
	void pure_virtual_method() {
		cout << " Child pure_virtual_method " << endl;
	}
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

③ 调用子类中实现的纯虚函数 :

	//在栈内存中创建一个 Child 对象, 并调用其重写的父类的方法
	Child child;
	//纯虚函数测试
	parent->pure_virtual_method();

  
 
  • 1
  • 2
  • 3
  • 4

④ 执行结果 :

 Child pure_virtual_method

  
 
  • 1


相关代码



1. 类的定义及继承相关代码 :

#pragma once

using namespace std;

//父类
class Parent{
public:
	void parent_method() {
		cout << " Parent parent_method " << endl;
	}

	//虚函数
	virtual void virtual_method() {
		cout << " Parent virtual_method " << endl;
	}

	//纯虚函数 , 类似于 Java 的抽象方法 , 
	//父类中声明后 , 该方法必须实现 , 否则编译时报错
	virtual void pure_virtual_method() = 0;
};

//父类
class Parent1 {
public:
	void parent_method() {
		cout << " Parent1 parent_method " << endl;
	}

	void parent_method1() {
		cout << " Parent1 parent_method1 " << endl;
	}
};

//子类
//继承父类 Parent
//继承作用域 : 默认私有继承 private 
class Child : public Parent, public Parent1 {
public:
	void parent_method() {
		//子类中调用父类的方法 , 该操作相当于 Java 中的 super 方法 
		Parent::parent_method();
		Parent1::parent_method();

		cout << " Child parent_method " << endl;
	}

	//重写父类的虚函数
	void virtual_method() {
		cout << " Child virtual_method " << endl;
	}

	//实现纯虚函数方法 , 该方法必须实现 , 否则会报错
	void pure_virtual_method() {
		cout << " Child pure_virtual_method " << 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
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

2. 调用上述方法 :

	//在栈内存中创建一个 Child 对象, 并调用其重写的父类的方法
	Child child;
	//调用子类重写的父类的方法
	child.parent_method();

	//调用子类没有重写的父类方法
	child.parent_method1();

	//多态

	//声明 Parent1 父类对象 , 为其赋值一个 Child 对象
	Parent* parent = new Child();

	//静态多态 : 在编译时 , 就可以确定函数调用的地址 ; 
	//	此时调用其 parent_method 方法 , 调用的是父类的方法
	parent->parent_method();

	//动态多态 : 在运行时 , 确定函数调用地址 , 
	//	此处调用的是子类实现的方法
	parent->virtual_method();

	//纯虚函数测试
	parent->pure_virtual_method();

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

执行结果 :

 Parent parent_method
 Parent1 parent_method
 Child parent_method
 Parent1 parent_method1
 Parent parent_method
 Child virtual_method
 Child pure_virtual_method

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/99690475

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。