본문 바로가기

C++ 프로그래밍

11주차_C++프로그래밍

  ✔️ 함수 중첩 (function overloading) 디폴트 인자(default parameter)

 

GPT에게 질문해보기

C++ 언어를 기반으로 객체 지향 프로그래밍의 특징

1. 캡슐화(Encapsulation): 데이터와 그 데이터를 처리하는 함수를 하나의 '클래스'라는 단위로 묶는 것을 말합니다. 이를 통해 데이터를 보호하고, 외부에서 접근을 제한할 수 있습니다.

class EncapsulationExample {
    private:
        int privateData;

    public:
        void setPrivateData(int data) {
            privateData = data;
        }

        int getPrivateData() {
            return privateData;
        }
};

2. 상속(Inheritance): 이미 정의된 클래스의 속성(데이터)과 메서드(함수)를 다른 클래스가 물려받아 사용하는 것을 말합니다. 이를 통해 코드의 재활용성을 높일 수 있습니다.

class Parent {
    public:
        void sayHello() {
            cout << "Hello from Parent class" << endl;
        }
};

class Child : public Parent {
    // Child class is inheriting from Parent class
};

 

3. 다형성(Polymorphism): 동일한 이름의 메서드가 상황에 따라 다르게 작동하는 것을 말합니다. 이를 통해 유연성과 확장성을 높일 수 있습니다.

class Base {
    public:
        virtual void print() {
            cout << "Base class print function" << endl;
        }
};

class Derived : public Base {
    public:
        void print() override {
            cout << "Derived class print function" << endl;
        }
};

 

function overloading을 지원하는 언어의 예

함수 오버로딩(Function Overloading)은 동일한 이름의 함수를 여러 개 정의하고, 그 함수들을 매개변수의 타입이나 개수에 따라서 구별하여 호출하는 기능을 말합니다.

함수 오버로딩을 지원하는 프로그래밍 언어는 다음과 같습니다:

 

1. C++: C++는 함수 오버로딩을 지원하며, 이는 C++의 주요한 특징 중 하나입니다.

void print(int i) {
  std::cout << " Here is int " << i << std::endl;
}
void print(double  f) {
  std::cout << " Here is float " << f << std::endl;
}

 

2. Java: Java도 함수 오버로딩을 지원합니다.

void demo(int a) {
   System.out.println("a: " + a);
}

void demo(int a, int b) {
   System.out.println("a and b: " + a + "," + b);
}

3. Python: Python은 기술적으로는 함수 오버로딩을 지원하지 않지만, 기본값이나 가변 인자를 사용하여 비슷한 효과를 낼 수 있습니다.

def foo(*args):
    if len(args) == 1:
        print("one argument: ", args[0])
    elif len(args) == 2:
        print("two arguments: ", args[0], args[1])

이 외에도 C#, PHP 등 많은 언어들이 함수 오버로딩을 지원합니다. 함수 오버로딩은 프로그래밍에서 중요한 기능 중 하나로, 필요에 따라 같은 이름의 함수를 다양한 방법으로 사용할 수 있게 해줍니다.

 

다형성(polymorphism)의 종류

출처 : 한성현 교수님 ppt

C++에서 다형성(polymorphism)의 종류

출처 : 한성현 교수님 ppt

 

virtual finction을 구현하는 것은 overriding

 

함수중첩(function overloading)

- 다형성을 구현하는 한가지 방법

- overloading은 이름이 같은 함수가 여러개 있다. -> 하나의 함수명을 여러 개의 유사 목적으로 사용 

- 다형성을 제공하는 C++에서는 하나의 함수 이름을 중첩해서 사용 가능하다.

 

함수 중첩 예(1)

#include <iostream>

int add(int i, int j)
{
	return (i + j);
}
double add(double i, double j)
{
	return (i + j);
}
int main()
{
	std::cout << add(10, 20) << std::endl;
	std::cout << add(10.5, 20.3) << std::endl;
	return 0;
}

컴파일러가 매개변수의 입력 자료형에 따라서 자동적으로 해당 함수를 연결해준다.

#include <iostream>

int add(int i, int j)
{
	return (i + j);
}
double add(double i, double j)
{
	return (i + j);
}
double add(int i, int j)//무조건 오버로딩 할 수 있는 것 아님 => 오류 : 매개변수가 같으면 오버로딩 불가
{
	return ((double)i + (double)j);
}
int main()
{
	std::cout << add(10, 20) << std::endl;
	std::cout << add(10.5, 20.3) << std::endl;
	return 0;
}

add(10,20)에 의해서는첫 번째 add()함수가 불려지고, add(10.5,20.3)에 의해서는 두 번째 add()함수가 불려진다.

즉, 컴파일러가 실매개변수의입력 자료형에 따라서 자동적으로 해당 함수를 연결해준다.

 

오류나는 이유 GPT 설명 : 

이 코드에서 문제가 되는 부분은 세 번째 add 함수입니다. 함수 오버로딩은 매개변수의 유형이나 개수가 다른 경우에만 가능합니다. 그런데 세 번째 add 함수는 첫 번째 add 함수와 매개변수의 유형과 개수가 동일하므로, 이 두 함수를 구분할 수 없습니다. 이 때문에 컴파일러가 오류를 발생시킵니다.

이 문제를 해결하려면 세 번째 add 함수의 매개변수 유형이나 개수를 변경하거나, 함수를 제거해야 합니다. 그런데 세 번째 add 함수가 double 형으로 변환하여 더하는 기능을 하므로, 매개변수 유형을 double로 변경하는 것이 적절해 보입니다.

 

함수 중첩 예(2)

문제) 임의의 형의 두 매개변수 중 큰 값을 반환하는 Max()라는 함수를 작성하시오. 즉, Max()함수가 매개변수로 int, double, char 등을 모두 가질 수 있도록 함수를 중첩시키시오.

#include <iostream>
int Max(int i, int j)
{
	return i > j ? i : j;
}
double Max(double i, double j)
{
	return i > j ? i : j;
}
char Max(char i, char j)
{
	return i > j ? i : j;
}
int main()
{
	std::cout << Max(1, 2) << std::endl;
	std::cout << Max(7.5, 3.6) << std::endl;
	std::cout << Max('A', 'B');
	return 0;
}

 

함수중첩 : C vs. C++

#include <iostream>
int add2(int i, int j)
{
	return (i + j);
}
int add3(int i, int j, int k)
{
	return (i + j + k);
}
int add4(int i, int j, int k, int l)
{
	return (i + j + k + l);
}
int main()
{
	std::cout << add2(1, 2) << std::endl;
	std::cout << add3(1, 2, 3) << std::endl;
	std::cout << add4(1, 2, 3, 4) << std::endl;
	return 0;
} //오버로딩 안함
#include <iostream>
int add(int i, int j)
{
	return (i + j);
}
int add(int i, int j, int k)
{
	return (i + j + k);
}
int add(int i, int j, int k, int l)
{
	return (i + j + k + l);
}
int main()
{
	std::cout << add(1, 2) << std::endl;
	std::cout << add(1, 2, 3) << std::endl;
	std::cout << add(1, 2, 3, 4) << std::endl;
	return 0;
} //오버로딩 함

컴파일러가 실매개변수의개수에 따라서 자동적으로 해당 함수를 연결해준다.

 

함수중첩을 하는 2가지 경우

#include <iostream>
int add(int i, int j)
{
	return (i + j);
}
float add(float i, float j)
{
	return (i + j);
}
double add(double i, double j)
{
	return (i + j);
}
int add(int i, int j, int k)
{
	return (i + j + k);
}
int add(int i, int j, int k, int l)
{
	return (i + j + k + l);
}
int main()
{
	std::cout << add(1, 2) << std::endl; // 매개변수의 형이 다른 경우
	std::cout << add(1.3f, 2.6f) << std::endl; // 매개변수의 형이 다른 경우
	std::cout << add(6.5, 3.8) << std::endl; // 매개변수의 형이 다른 경우
	std::cout << add(1, 2, 3) << std::endl; // 매개변수의 개수가 다른 경우
	std::cout << add(1, 2, 3, 4) << std::endl; // 매개변수의 개수가 다른 경우
	return 0;
}

매개변수의 형이나 개수가 다른 경우 중첩할 수 있다.

 

생성자 함수 중첩 예

#include <iostream>
class Dog {
private:
	int age;
public:
	Dog() { age = 1; } // 매개변수가 없는 생성자, 자동 inline
	Dog(int a) { age = a; } // 매개변수가 하나인 생성자
	~Dog();
	int getAge();
	void setAge(int a);
};
Dog::~Dog()
{
	std::cout << "소멸";
}
int Dog::getAge()
{
	return age;
}
void Dog::setAge(int a)
{
	age = a;
}
int main()
{
	Dog happy(2), meri; //매개변수가 있는 생성자 호출(happy), 매개변수가 없는 생성자 호출(meri)
	std::cout << happy.getAge() << "," << meri.getAge();
	return 0;
}

#define _CRT_SECURE_NO_WARNINGS // sscanf()함수 오류 제거
#include <stdio.h> // sscanf()함수 선언
#include <iostream>
class Date {
	int day, month, year;
public:
	Date(const char* s) { sscanf(s, "%d%*c%d%*c%d", &month, &day, &year); }
	Date(int m, int d, int y) { day = d; month = m; year = y; }
	void print() { std::cout << year << "년 " << month << "월 " << day << "일" << std::endl; }
};
int main()
{
	Date d1("10/29/2021");
	Date d2(10, 30, 2021);
	d1.print();
	d2.print();
	return 0;
}

 

디폴트 인자(default parameter, default argument)

: 디폴트 매개변수 

- int add(int, int); //매개변수 2개

- C++에서는 함수를 호출할 때 별도의 매개변수를 전달하지 않아도 기본적인 값을 전달하도록

  함수 원형을 선언할 때 디폴트 값을 지정할 수 있다.

- 해당 매개변수가 주어지지 않으면 디폴트 인자 값이 할당된다.

- 모든 매개변수에 디폴트 값을 줄 필요는 없으며 필요한 곳에만 준다.

- 디폴트 매개변수의 사용은 함수 중첩의 축약형이다.

- 디폴트 매개변수를 갖는 함수를 만들 때, main()함수 전에 함수 선언을 하면 선언부에만 디폴트 인자를 지정해야 한다.

- int add(int i=1, int j=2);// 선언부에 디폴트 인자 작성

- 일단 디폴트 매개변수를 정의하기 시작하면 그 다음(오른쪽)의 매개변수들은 모두 디폴트 매개변수를 가져야 한다.

- int add(int i=1, int j);//오류

#include <iostream>
int add(int i=1, int j=2) // 형식매개변수
{
	return(i + j);
}
int main()
{
	std::cout << add() << ","; // 실매개변수 없음, 3
	std::cout << add(10) << ","; // 실매개변수 한 개, 12
	std::cout << add(10, 20); // 실매개변수 두개, 30
	return 0;
}

 

위 코드가 실행되기 위해서는 실매개변수 i, j에 대한 값이 있어야 하는데 둘다 없거나 하나만 있는 경우에는 오류가 난다.

그러나 디폴트 인자 i=1, j=2로 값을 담아두면, 매개변수가 없을 때 디폴트 인자의 값이 할당되어 실행되고 결과가 나온다.

 

#include <iostream>
int add(int i = 1, int j = 2); // 형식매개변수
int main()
{
	std::cout << add() << ","; // 실매개변수 없음, 3
	std::cout << add(10) << ","; // 실매개변수 한 개, 12
	std::cout << add(10, 20); // 실매개변수 두개, 30
	return 0;
}
int add(int i, int j)
{
	return(i + j);
}

선언과 정의를 구분지어 놓는 경우, 선언부에만 디폴트 값을 준다. 정의부에는 쓸 필요가 없다.

-> 디폴트 매개변수를 갖는 함수를 만들 때, main()함수 전에 함수 선언을 하면 선언부에만 디폴트 인자를 지정해야 한다.

#include <iostream>
class Dog {
private:
	int age;
public:
	Dog(int a = 1); // 디폴트 매개변수를 갖는 생성자
	// Dog() { age = 1; } -> 두 번 쓸 필요 없이 디폴트 매개변수 이용
	~Dog();
	int getAge();
	void setAge(int a);
};
Dog::Dog(int a) { age = a; } //선언부에만 디폴트 인자를 쓴다.
Dog::~Dog() { std::cout << "소멸\n"; }
int Dog::getAge() { return age; }
void Dog::setAge(int a) { age = a; }
int main()
{
	Dog meri, happy(5);
	std::cout << happy.getAge() << "," << meri.getAge() << std::endl;
	return 0;
}

 

디폴트 인자 응용

문제) 2개에서 4개의 정수형 매개변수를 입력받아 그 곱(합)한 결과를 출력할 수 있는 Gop()(Hap()) 이라는 함수를 디폴트 인자를 이용하여 구현

#include <iostream>
int Gop(int i, int j, int k = 1, int l = 1)
{
	return(i * j * k * l);
}
int main()
{
	std::cout << Gop(1, 2) << std::endl; // 1*2*1*1
	std::cout << Gop(1, 2, 3) << std::endl; // 1*2*3*1
	std::cout << Gop(1, 2, 3, 4) << std::endl;// 1*2*3*4
	return 0;
}

'C++ 프로그래밍' 카테고리의 다른 글

13주차_C++프로그래밍  (0) 2023.11.29
12주차_C++프로그래밍  (0) 2023.11.22
10주차_C++프로그래밍  (0) 2023.11.08
9주차_C++프로그래밍  (1) 2023.11.01
7주차_C++프로그래밍  (1) 2023.10.18