예제를 사용한 C++ 다형성

C++의 다형성이란 무엇입니까?

C++에서 다형성으로 인해 멤버 함수는 이를 호출/호출하는 개체에 따라 다르게 동작합니다. 다형성(Polymorphism)은 다양한 형태를 갖는다는 뜻을 지닌 그리스어이다. 상속을 통해 관련된 클래스의 계층 구조가 있을 때 발생합니다.

예를 들어 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. 정수 매개변수 i를 사용하는 test라는 함수를 만듭니다. {는 함수 테스트 본문의 시작을 표시합니다.
  4. 위의 기능 테스트가 호출/호출되면 실행될 명령문입니다.
  5. 위의 기능 테스트 본문을 마칩니다.
  6. float 매개변수 f를 사용하는 test라는 함수를 만듭니다. {는 함수 테스트 본문의 시작을 표시합니다.
  7. 위의 기능 테스트가 호출/호출되면 실행될 명령문입니다.
  8. 위 기능 테스트 본문을 마칩니다.
  9. 문자 매개 변수 ch를 사용하는 test라는 함수를 만듭니다. {는 함수 테스트 본문의 시작을 표시합니다.
  10. 위의 기능 테스트가 호출/호출되면 실행될 명령문입니다.
  11. 위 기능 테스트 본문을 마칩니다.
  12. main() 함수를 호출합니다. {는 함수 본문의 시작을 표시합니다.
  13. test 함수를 호출하고 5를 인수 값으로 전달합니다. 이는 정수 인수를 허용하는 테스트 함수, 즉 첫 번째 테스트 함수를 호출합니다.
  14. test 함수를 호출하고 5.5를 인수 값으로 전달합니다. 이는 float 인수를 허용하는 테스트 함수, 즉 두 번째 테스트 함수를 호출합니다.
  15. test 함수를 호출하고 XNUMX를 인수 값으로 전달합니다. 그러면 문자 인수를 허용하는 테스트 함수, 즉 세 번째 테스트 함수가 호출됩니다.
  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. Com이라는 클래스를 만듭니다.plex번호 {는 클래스 본문의 시작을 표시합니다.
  4. 변수를 비공개로 표시하려면 비공개 액세스 한정자를 사용하세요. 즉, 해당 변수는 클래스 내에서만 액세스할 수 있습니다.
  5. 실수와 초과라는 두 개의 정수 변수를 정의합니다.
  6. public 액세스 한정자를 사용하여 생성자를 public으로 표시합니다. 즉, 외부에서도 액세스할 수 있습니다. 수업.
  7. 클래스 생성자를 만들고 변수를 초기화합니다.
  8. real 변수의 값을 초기화합니다.
  9. 변수의 값을 초기화합니다.
  10. 생성자 본문의 끝입니다.
  11. + 연산자의 의미를 재정의해야 합니다.
  12. Com 유형의 데이터 유형 결과를 생성합니다.plex번호
  13. com에 + 연산자 사용plex 숫자. 이 줄은 숫자의 실수 부분을 다른 숫자의 실수 부분에 추가합니다.
  14. com에 + 연산자 사용plex 숫자. 이 줄은 숫자의 허수 부분을 다른 숫자의 허수 부분에 추가합니다.
  15. 프로그램은 성공적으로 실행되면 변수 결과 값을 반환합니다.
  16. + 연산자의 새로운 의미, 즉 오버로딩에 대한 정의를 마칩니다.
  17. print() 메서드를 호출합니다.
  18. 새 com을 인쇄하세요.plex 콘솔에 추가한 후의 번호입니다.
  19. print() 함수 본문의 끝입니다.
  20. Com 본체의 끝plex번호 클래스.
  21. main() 함수를 호출합니다.
  22. real과 com의 값을 모두 전달합니다.plex 추가할 부분. 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. 공개 액세스 수정자를 사용하여 생성하려는 함수를 공개적으로 액세스할 수 있도록 설정합니다. 이 클래스 외부에서 액세스할 수 있습니다.
  5. eat이라는 공개 함수를 만듭니다. {는 함수 본문의 시작을 표시합니다.
  6. eat() 함수가 호출될 때 cout 함수에 추가된 명령문을 인쇄합니다.
  7. eat() 함수 본문의 끝입니다.
  8. 포유류 클래스의 몸체 끝.
  9. Mammal 클래스를 상속하는 Cow라는 클래스를 만듭니다. Cow는 파생 클래스이고 Mammal은 기본 클래스입니다. {는 이 클래스의 시작을 표시합니다.
  10. 공개 액세스 수정자를 사용하여 생성하려는 함수를 공개적으로 액세스할 수 있도록 표시합니다. 이 클래스 외부에서 액세스할 수 있습니다.
  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();      
	}

출력:

C++ 가상 함수

다음은 코드의 스크린샷입니다.

C++ 가상 함수

코드 설명 :

  1. 해당 기능을 사용하려면 코드에 iostream 헤더 파일을 포함하세요.
  2. 클래스를 호출하지 않고 사용하려면 코드에 std 네임스페이스를 포함하세요.
  3. ClassA라는 클래스를 만듭니다.
  4. 클래스 멤버를 공개적으로 액세스할 수 있도록 표시하려면 public 액세스 한정자를 사용하세요.
  5. show()라는 가상 함수를 만듭니다. 공개적인 기능이 될 것입니다.
  6. show()가 호출될 때 인쇄할 텍스트입니다. endl은 끝줄을 의미하는 C++ 키워드입니다. 마우스 커서를 다음 줄로 이동시킵니다.
  7. 가상 함수 show()의 본문 끝입니다.
  8. ClassA 클래스 본문의 끝입니다.
  9. ClassA 클래스를 상속하는 ClassB라는 새 클래스를 만듭니다. ClassA는 기본 클래스가 되고 ClassB는 파생 클래스가 됩니다.
  10. 클래스 멤버를 공개적으로 액세스할 수 있도록 표시하려면 public 액세스 한정자를 사용하세요.
  11. 기본 클래스에서 파생된 가상 함수 show()를 재정의합니다.
  12. 파생 클래스에 정의된 show() 함수가 호출될 때 콘솔에 인쇄할 텍스트입니다.
  13. show() 함수 본문의 끝입니다.
  14. 파생 클래스 ClassB의 본문 끝입니다.
  15. main() 함수를 호출합니다. 프로그램 논리는 해당 본문 내에 추가되어야 합니다.
  16. a라는 포인터 변수를 만듭니다. ClassA라는 클래스를 가리킵니다.
  17. ClassB라는 클래스의 인스턴스를 만듭니다. 인스턴스 이름은 b로 지정됩니다.
  18. 변수 a에 주소 b에 저장된 값을 할당합니다.
  19. 파생 클래스에 정의된 show() 함수를 호출합니다. 후기 바인딩이 구현되었습니다.
  20. main() 함수 본문의 끝입니다.

컴파일 타임 다형성 대. 런타임 다형성

둘 사이의 주요 차이점은 다음과 같습니다.

컴파일 타임 다형성 런타임 다형성
초기 바인딩 또는 정적 다형성이라고도 합니다. 후기/동적 바인딩 또는 동적 다형성이라고도 합니다.
메소드는 컴파일 시간 동안 호출/호출됩니다. 런타임 중에 메서드가 호출/호출됩니다.
함수 오버로딩과 연산자 오버로딩을 통해 구현됨 메서드 재정의 및 가상 함수를 통해 구현됨
예, 메소드 오버로딩. 많은 메서드가 비슷한 이름을 가질 수 있지만 인수의 수나 유형이 다를 수 있습니다. 예, 메서드 재정의. 많은 메서드가 비슷한 이름과 동일한 프로토타입을 가질 수 있습니다.
컴파일 시간 동안 메소드 검색이 수행되므로 실행 속도가 빨라집니다. 메소드 발견자가 런타임 중에 수행되므로 실행 속도가 느려집니다.
컴파일 시간 동안 모든 것이 알려지기 때문에 문제 해결에 대한 유연성이 떨어집니다. com 문제 해결을 위해 많은 유연성이 제공됩니다.plex 런타임 중에 메소드가 발견되기 때문에 문제가 발생합니다.

요약

  • 다형성은 다양한 형태를 갖는다는 뜻이다.
  • 상속을 통해 관련된 클래스의 계층 구조가 있을 때 발생합니다.
  • 다형성을 사용하면 함수를 호출/호출하는 개체에 따라 함수가 다르게 동작할 수 있습니다.
  • 컴파일 타임 다형성에서는 호출할 함수가 컴파일 타임에 설정됩니다.
  • 런타임 다형성에서는 호출될 함수가 런타임 중에 설정됩니다.
  • 컴파일 타임 다형성은 함수 오버로딩과 연산자 오버로딩을 통해 결정됩니다.
  • 함수 오버로딩에는 이름은 비슷하지만 인수가 다른 함수가 많이 있습니다.
  • 매개변수의 수나 유형이 다를 수 있습니다.
  • 연산자 오버로딩에서는 다음에 대한 새로운 의미가 정의됩니다. C++ 연산자.
  • 런타임 다형성은 함수 재정의를 통해 달성됩니다.
  • 함수 재정의에서 파생 클래스는 기본 클래스에 정의된 함수에 새로운 정의를 제공합니다.