亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> C语言

C++ 多态与示例

什么是 C++ 中的多态性?

在 C++ 中,多态性会导致成员函数的行为基于调用/调用它的对象而有所不同。多态性是一个希腊词,意思是有多种形式。当您具有通过继承相关的类层次结构时,就会发生这种情况。

例如,假设我们有函数 makeSound()。当一只猫调用这个函数时,它会发出喵喵的声音。当一头牛调用相同的函数时,它会发出哞哞的声音。

虽然我们只有一个函数,但它在不同的情况下表现不同。功能有多种形式;因此,我们实现了多态性。

在本 C++ 教程中,您将学习:

多态的类型

C++ 支持两种类型的多态:

编译时多态

您可以通过匹配参数的数量和类型来调用重载函数。该信息在编译时存在。这意味着 C++ 编译器将在编译时选择正确的函数。

编译时多态性是通过函数重载和运算符重载来实现的。

函数重载

当我们有许多名称相似但参数不同的函数时,就会发生函数重载。参数可能在数量或类型方面有所不同。

示例 1:

#include <iostream> 
using namespace std;

void test(int i) {
	cout << " The int is " << i << endl;
}
void test(double  f) {
	cout << " The float is " << f << endl;
}
void test(char const *ch) {
	cout << " The char* is " << ch << endl;
}

int main() {
	test(5);
	test(5.5);
	test("five");
	return 0;
}

输出:

下面是代码截图:

代码说明:

  1. 将 iostream 头文件包含到我们的代码中。我们将能够使用它的功能。
  2. 在我们的代码中包含 std 命名空间。我们将能够在不调用它的情况下使用它的类。
  3. 创建一个名为 test 的函数,它接受一个整数参数 i。 { 标志着函数测试体的开始。
  4. 调用/调用上述函数测试时要执行的语句。
  5. 上述函数测试体结束。
  6. 创建一个名为 test 的函数,它接受一个浮点参数 f。 { 标志着函数测试体的开始。
  7. 调用/调用上述函数测试时要执行的语句。
  8. 上述函数测试的主体结束。
  9. 创建一个名为 test 的函数,它接受一个字符参数 ch。 { 标志着函数测试体的开始。
  10. 调用/调用上述函数测试时要执行的语句。
  11. 上述函数测试的主体结束。
  12. 调用 main() 函数。 { 标记函数体的开始。
  13. 调用函数 test 并将 5 作为参数的值传递给它。这将调用接受整数参数的测试函数,即第一个测试函数。
  14. 调用函数 test 并将 5.5 作为参数的值传递给它。这将调用接受浮点参数的测试函数,即第二个测试函数。
  15. 调用函数 test 并将 5 作为参数的值传递给它。这将调用接受字符参数的测试函数,即第三个测试函数。
  16. 如果程序成功运行,它必须返回一个值。
  17. main() 函数体的结尾。

我们有三个名称相同但参数类型不同的函数。我们已经实现了多态性。

运算符重载

在运算符重载中,我们为 C++ 运算符定义了新的含义。它还改变了操作员的工作方式。例如,我们可以定义 + 运算符来连接两个字符串。我们知道它是用于添加数值的加法运算符。在我们定义之后,当放在整数之间时,它会添加它们。当放置在字符串之间时,它将连接它们。

示例 2:

#include<iostream> 
using namespace std;

class ComplexNum {
private:
	int real, over;
public:
	ComplexNum(int rl = 0, int ov = 0) {
		real = rl;   
		over = ov; 
	}

	ComplexNum operator + (ComplexNum const &obj) {
		ComplexNum result;
		result.real = real + obj.real;
		result.over = over + obj.over;
		return result;
	}
	void print() { 
		cout << real << " + i" << over << endl; 
	}
};
int main()
{
	ComplexNum c1(10, 2), c2(3, 7);
	ComplexNum c3 = c1+c2;
	c3.print();
}

输出:

下面是代码截图:

代码说明:

  1. 将 iostream 头文件包含到我们的程序中,以便使用它的功能。
  2. 将 std 命名空间包含在我们的程序中,以便在不调用它的情况下使用它的类。
  3. 创建一个名为 ComplexNum 的类。 { 标志着类主体的开始。
  4. 使用 private 访问修饰符将变量标记为私有,这意味着它们只能从类内部访问。
  5. 定义两个整数变量,real 和 over。
  6. 使用 public 访问修饰符将构造函数标记为 public,这意味着即使从类外部也可以访问它。
  7. 创建类构造函数并初始化变量。
  8. 初始化变量real的值。
  9. 初始化过变量的值。
  10. 构造函数体结束。
  11. 我们需要重写 + 运算符的含义。
  12. 创建 ComplexNum 类型的数据类型结果。
  13. 对复数使用 + 运算符。此行会将一个数字的实部添加到另一个数字的实部。
  14. 对复数使用 + 运算符。这条线将一个数字的虚部添加到另一个数字的虚部。
  15. 程序执行成功后会返回变量result的值。
  16. 定义结束+运算符的新含义,即重载。
  17. 调用 print() 方法。
  18. 在控制台上打印添加后的新复数。
  19. print() 函数体结束。
  20. ComplexNum 类的主体结束。
  21. 调用 main() 函数。
  22. 传递要添加的实部和复部的值。 c1 的第一部分将添加到 c2 的第一部分,即 10+3。 c1的第二部分会加到c的第二部分,即2+7。
  23. 使用重载的 + 运算符执行操作,并将结果存储在变量 c3 中。
  24. 在控制台上打印变量 c3 的值。
  25. main() 函数体结束。

运行时多态

当在运行时而不是在编译时调用/调用对象的方法时,就会发生这种情况。运行时多态性是通过函数重写来实现的。要调用/调用的函数是在运行时建立的。

函数重写

当基类的函数在派生类中被赋予新定义时,就会发生函数覆盖。那时,我们可以说基函数已被覆盖。

例如:

#include <iostream>
using namespace std;
class Mammal {

public:
	void eat() {

		cout << "Mammals eat...";
	}

};

class Cow: public Mammal {

public:
	void eat() {

		cout << "Cows eat grass...";
	}
};
int main(void) {

	Cow c = Cow();

	c.eat();

	return 0;

}

输出:

下面是代码截图:

代码说明:

  1. 将 iostream 头文件导入到我们的程序中以使用它的功能。
  2. 将 std 命名空间包含在我们的程序中,以便在不调用它的情况下使用它的类。
  3. 创建一个名为 Mammal 的类。 { 标志着类主体的开始。
  4. 使用 public 访问修饰符将我们即将创建的函数设置为可公开访问。可以从此类外部访问它。
  5. 创建一个名为 eat 的公共函数。 { 标记函数体的开始。
  6. 打印调用函数eat() 时添加到cout 函数的语句。
  7. 函数体eat()的结束。
  8. 哺乳动物类主体的结尾。
  9. 创建一个名为 Cow 的类,它继承了 Mammal 类。 Cow 是派生类,而 Mammal 是基类。 { 标志着这个类的开始。
  10. 使用 public 访问修饰符将我们即将创建的函数标记为可公开访问。它将可以从这个类之外访问。
  11. 覆盖基类中定义的函数eat()。 { 标记函数体的开始。
  12. 调用此函数时在控制台上打印的语句。
  13. 函数体eat()的结束。
  14. Cow 类主体的结尾。
  15. 调用 main() 函数。 { 标记此函数主体的开始。
  16. 创建 Cow 类的一个实例,并将其命名为 c。
  17. 调用 Cow 类中定义的eat() 函数。
  18. 程序必须在成功完成后返回一个值。
  19. main() 函数结束。

C++ 虚函数

虚函数是在 C++ 中实现运行时多态性的另一种方式。它是在基类中定义并在派生类中重新定义的特殊函数。要声明一个虚函数,你应该使用 virtual 关键字。关键字应该在基类中的函数声明之前。

如果继承了虚函数类,则虚类会重新定义虚函数以满足其需要。例如:

#include <iostream>  
using namespace std;
class ClassA {
		public:
		virtual void show() {
			cout << "The show() function in base class invoked..." << endl;
		}
	};
	class ClassB :public ClassA {
	public:
		void show() 	{
			cout << "The show() function in derived class invoked...";
		}
	};
	int main() {
		ClassA* a;   
		ClassB b;
		a = &b;
		a->show();      
	}

输出:

下面是代码截图:

代码说明:

  1. 在代码中包含 iostream 头文件以使用其功能。
  2. 在我们的代码中包含 std 命名空间以使用它的类而不调用它。
  3. 创建一个名为 ClassA 的类。
  4. 使用公共访问修饰符将类成员标记为可公开访问。
  5. 创建一个名为 show() 的虚函数。这将是一项公共职能。
  6. 调用 show() 时要打印的文本。 endl 是 C++ 关键字,表示结束行。它将鼠标光标移动到下一行。
  7. 虚函数 show() 的主体结束。
  8. ClassA 类主体的结尾。
  9. 创建一个名为 ClassB 的新类,该类继承类 ClassA。 ClassA 成为基类,而 ClassB 成为派生类。
  10. 使用公共访问修饰符将类成员标记为可公开访问。
  11. 重新定义基类中派生的虚函数show()。
  12. 调用派生类中定义的 show() 函数时在控制台上打印的文本。
  13. show() 函数主体的结尾。
  14. 派生类 ClassB 主体的结尾。
  15. 调用 main() 函数。程序逻辑应添加到其主体中。
  16. 创建一个名为a的指针变量。它指向名为 ClassA 的类。
  17. 创建一个名为 ClassB 的类的实例。该实例被命名为 b。
  18. 将值存储在变量 a 中的地址 b 中。
  19. 调用派生类中定义的 show() 函数。后期绑定已实施。
  20. main() 函数体的结尾。

编译时多态性对比。运行时多态

以下是两者之间的主要区别:

编译时多态性 运行时多态性 也称为早期绑定或静态多态性也称为后期/动态绑定或动态多态性在编译时调用/调用方法在运行时调用/调用方法通过函数重载和运算符重载实现通过方法重写和虚函数例如方法重载。许多方法可能具有相似的名称,但参数的数量或类型不同例如,方法覆盖。许多方法可能具有相似的名称和相同的原型。由于方法发现是在编译期间完成的,因此执行速度更快由于方法发现器是在运行时完成的,因此执行速度较慢。由于在编译期间一切都是已知的,因此解决问题的灵活性较低。灵活性很大提供用于解决复杂问题,因为方法是在运行时发现的。

总结:


C语言

  1. 在 C++ 编程中将数组传递给函数
  2. C++ 中的运算符示例:什么是、类型和程序
  3. 带有示例的 C++ Switch Case 语句
  4. C++ 动态分配数组的例子
  5. 带有示例的 C++ 运算符重载
  6. C++ 结构与示例
  7. C++ 中的 std::list 示例
  8. 带有程序示例的 C++ 函数
  9. 结构和类的区别:用 C++ 示例解释
  10. 带有程序示例的 C 库中的 calloc() 函数
  11. C 库中的 free() 函数:如何使用?通过示例学习
  12. Python String strip() 函数与示例