본문 바로가기
C++

[C++ 프로그래밍] 11주차 함수중첩, 디폴트 인자

by heeaeeeee 2023. 11. 16.

1. function overloading을 지원하는 모든 프로그래밍언어 설명

1. C++: C++는 함수 오버로딩을 지원하는 대표적인 언어입니다. 같은 이름의 함수를 여러 개 정의하고, 이들 함수가 매개변수의 타입이나 개수에 따라 다르게 동작하도록 할 수 있습니다.
2.Java: Java도 함수 오버로딩을 지원합니다. 메서드의 이름은 같지만 매개변수의 타입이나 개수가 다른 여러 개의 메서드를 한 클래스 내에서 정의할 수 있습니다.
3.C#: C#은 C++처럼 함수 오버로딩을 지원합니다. 동일한 이름의 메서드를 정의하되, 매개변수의 타입이나 개수를 다르게 해서 다양한 동작을 정의할 수 있습니다.
4.Python: Python은 기본적으로 함수 오버로딩을 지원하지 않습니다. 하지만, 여러 방법으로 이를 구현할 수 있습니다. 예를 들어, 다양한 타입의 인수를 받을 수 있는 가변 인수를 사용하거나, 데코레이터와 같은 기능을 이용하여 구현할 수 있습니다.
5.JavaScript: JavaScript는 동적 타입 언어로서, 기본적으로 함수 오버로딩을 지원하지 않습니다. 하지만, 매개변수의 개수나 타입을 체크하여 함수 내부에서 다르게 동작하도록 구현할 수 있습니다.
6.TypeScript: TypeScript는 JavaScript의 상위 집합으로, JavaScript에는 없는 정적 타입 기능을 제공합니다. 이를 통해 함수 오버로딩을 지원합니다.
7.PHP: PHP는 함수 오버로딩을 직접적으로 지원하지 않습니다. 하지만, 가변 인수나 기본값 인수를 사용하여 비슷한 동작을 구현할 수 있습니다.
8.Kotlin: Kotlin은 함수 오버로딩을 지원합니다. 같은 이름의 함수를 매개변수의 타입이나 개수가 다르게 여러 개 정의할 수 있습니다.
9.Swift: Swift 역시 함수 오버로딩을 지원합니다. 함수 이름은 같지만 매개변수의 타입이나 개수가 다른 여러 함수를 정의할 수 있습니다.
10.Scala: Scala는 함수 오버로딩을 지원합니다. 같은 이름의 함수를 매개변수의 타입이나 개수가 다르게 여러 개 정의할 수 있습니다.

2. 객체지향의 3가지 특징,  c++ 소스로 설명

1. 캡슐화(Encapsulation): 캡슐화는 객체의 데이터와 그 데이터를 조작하는 함수를 하나로 묶는 기법입니다. 이를 통해 객체 내부 데이터를 외부에서 직접 접근하는 것을 제한하고, 함수를 통해서만 데이터를 조작할 수 있도록 합니다.
2. 상속(Inheritance): 상속은 기존의 클래스를 확장하여 새로운 클래스를 생성하는 기법입니다. 이를 통해 코드의 재사용성을 높이고, 중복된 코드를 줄일 수 있습니다.
3. 다형성(Polymorphism): 다형성은 하나의 이름이나 함수가 여러 형태로 동작하는 것을 의미합니다. 이를 통해 프로그램의 유연성과 확장성을 높일 수 있습니다.

#include <iostream>

// 캡슐화 예제
class Animal {
private:
    std::string name; // private 변수로 캡슐화

public:
    Animal(std::string n) : name(n) {} // 생성자
    void setName(std::string n) { name = n; } // setter
    std::string getName() { return name; } // getter

    virtual void makeSound() { // 다형성 예제
        std::cout << name << " makes a sound." << std::endl;
    }
};

// 상속 예제
class Dog : public Animal {
public:
    Dog(std::string n) : Animal(n) {} // 생성자

    // 다형성 예제
    void makeSound() override { // 부모 클래스의 makeSound() 메서드를 오버라이드
        std::cout << getName() << " barks." << std::endl;
    }
};

int main() {
    Dog myDog("Pochi");
    myDog.makeSound(); // "Pochi barks." 출력

    Animal* animalPtr = &myDog;
    animalPtr->makeSound(); // "Pochi barks." 출력. 다형성에 의해 Dog 클래스의 makeSound() 메서드가 호출됨

    return 0;
}

3. c++에서 polymorphism 구현하는 방법 설명

C++에서 다형성(Polymorphism)을 구현하는 기본적인 방법은 가상 함수(virtual function)를 사용하는 것입니다. 가상 함수는 기본 클래스에서 선언되고 파생 클래스에서 오버라이드(재정의)됩니다.

#include <iostream>

// 기본 클래스 Animal 정의
class Animal {
public:
    virtual void makeSound() { // 가상 함수 makeSound 선언
        std::cout << "The animal makes a sound" << std::endl;
    }
};

// 파생 클래스 Dog 정의
class Dog : public Animal {
public:
    void makeSound() override { // 가상 함수 makeSound 오버라이드
        std::cout << "The dog barks" << std::endl;
    }
};

// 파생 클래스 Cat 정의
class Cat : public Animal {
public:
    void makeSound() override { // 가상 함수 makeSound 오버라이드
        std::cout << "The cat meows" << std::endl;
    }
};

int main() {
    Animal* animal1 = new Dog(); // Dog 객체를 Animal 포인터로 가리킴
    Animal* animal2 = new Cat(); // Cat 객체를 Animal 포인터로 가리킴
    animal1->makeSound(); // "The dog barks" 출력
    animal2->makeSound(); // "The cat meows" 출력
    delete animal1;
    delete animal2;
    return 0;
}

4. 다형성(polymorphism)의 종류

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

6. 함수 오버로딩(중첩)

같은 이름의 함수를 여러개 사용할 수 있다.

7. 함수 중첩(function overloading)

8. C++은 함수 중첩 가능 ( C의 경우 함수 중첩 불가능)

9. 함수 중첩 예1

#include <iostream>
int add(int i, int j)
{
	return (i + j);
}
double add(int i, int j)
{
	return ((double)i + (double)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;
}

add(10,20)에 의해서는첫 번째 add()함수가 불려지고, add(10.5,20.3)에 의해서는 두 번째 add()함수가 불려진다. 즉, 컴파일러가 실매개변수의입력 자료형에 따라서 자동적으로 해당 함수를 연결해준다.

10. 함수 중첩 예2

#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;
}

세 개의 Max()함수를 중첩시키고 있다. 이렇게 함수의 실행 코드가 모두 같은 경우에는 함수 중첩에 만족하지 말고 18장에서 설명할 템플릿(template)을 사용하는 것이 더 좋다. template T Max(T i, T j)

11. 함수중첩을 하는 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 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;
	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;
}

12. 11번 소스 설명

#include <iostream> // iostream 헤더 파일을 include하여 입출력 기능을 사용할 수 있도록 합니다.
// 정수 두 개를 인자로 받아서 더한 결과를 반환하는 함수입니다.
int add(int i, int j)
{
	return (i + j); // 두 정수를 더한 결과를 반환합니다.
}
// float형 실수 두 개를 인자로 받아서 더한 결과를 반환하는 함수입니다.
float add(float i, float j)
{
	return (i + j); // 두 실수를 더한 결과를 반환합니다.
}
// double형 실수 두 개를 인자로 받아서 더한 결과를 반환하는 함수입니다.
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); // 네 정수를 더한 결과를 반환합니다.
}
// 프로그램의 시작점인 main 함수입니다.
int main()
{
	std::cout << add(1, 2) << std::endl; // 정수 두 개를 더하는 add 함수를 호출하고 결과를 출력합니다.
	std::cout << add(1.3f, 2.6f) << std::endl; // float형 실수 두 개를 더하는 add 함수를 호출하고 결과를 출력합니다.
	std::cout << add(6.5, 3.8) << std::endl; // double형 실수 두 개를 더하는 add 함수를 호출하고 결과를 출력합니다.
	std::cout << add(1, 2, 3) << std::endl; // 정수 세 개를 더하는 add 함수를 호출하고 결과를 출력합니다.
	std::cout << add(1, 2, 3, 4) << std::endl; // 정수 네 개를 더하는 add 함수를 호출하고 결과를 출력합니다.
	return 0; // 프로그램이 정상적으로 종료되었음을 운영체제에 알립니다.
}

13. 생성자 중첩

14. 생성자 중첩 예1

#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(5), meri;
	std::cout << happy.getAge() << "," << meri.getAge();
	return 0;
}

이 소스의 장점은 초기값을 다양하게 주는 기회를 제공한다.

15. 생성자 중첩 예2

#include <iostream>
using std::cout;
using std::endl;
class Dog {
private:
	int age;
public:
	Dog() { age = 1; }
	// 매개변수가 없는 생성자
	Dog(int a) { age = a; }
	// 매개변수가 하나인 생성자
	~Dog();
	int getAge();
	void setAge(int a);
};
Dog::~Dog()
{
	std::cout << "소멸\n";
}
int Dog::getAge()
{
	return age;
}
void Dog::setAge(int a)
{
	age = a;
}
int main()
{
	Dog happy[5];
	Dog meri[5] = { 1,2,3,4,5 };
	for (int i = 0; i < 5; i++)
		std::cout << happy[i].getAge() <<
		"," << meri[i].getAge() << std::endl;
	return 0;
}

16. default parameter를 사용하는 프로그래밍 언어 설명

1. C++: C++에서는 함수 선언 시 매개변수의 기본값을 지정할 수 있습니다. 이 기본값은 함수 호출 시 해당 매개변수에 대한 인수가 제공되지 않았을 때 사용됩니다.

void foo(int x = 10) {
    std::cout << x << std::endl;
}

foo();  // 10 출력
foo(20);  // 20 출력

2. Python: Python에서는 함수를 정의할 때 매개변수의 기본값을 지정할 수 있습니다. 이 기본값은 함수 호출 시 해당 매개변수에 대한 인수가 제공되지 않았을 때 사용됩니다.

def foo(x=10):
    print(x)

foo()  # 10 출력
foo(20)  # 20 출력

3. JavaScript: JavaScript에서는 ES6부터 함수 매개변수의 기본값을 지정할 수 있습니다. 이 기본값은 함수 호출 시 해당 매개변수에 대한 인수가 undefined인 경우에 사용됩니다.

function foo(x = 10) {
    console.log(x);
}

foo();  // 10 출력
foo(20);  // 20 출력

4. PHP: PHP에서는 함수를 정의할 때 매개변수의 기본값을 지정할 수 있습니다. 이 기본값은 함수 호출 시 해당 매개변수에 대한 인수가 제공되지 않았을 때 사용됩니다.

function foo($x = 10) {
    echo $x;
}

foo();  // 10 출력
foo(20);  // 20 출력

5. Swift: Swift에서는 함수를 정의할 때 매개변수의 기본값을 지정할 수 있습니다. 이 기본값은 함수 호출 시 해당 매개변수에 대한 인수가 제공되지 않았을 때 사용됩니다.

func foo(x: Int = 10) {
    print(x)
}

foo()  // 10 출력
foo(x: 20)  // 20 출력

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

18. 디폴트 인자 예

#include <iostream>
int add(int i = 1, int j = 2); //선언부에 작성
//i를 주면 j도 줘야한다. j만 주는 것은 가능하다. 
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);
}

형식매개변수보다 적은 실매개변수로 호출할 경우 왼쪽의 매개변수부터 값을 할당받는다. 

19. 디폴트 인자를 갖는 생성자 예

#include <iostream>
class Dog {
private:
	int age;
public:
	Dog(int a = 1) { age = a; }
	// 디폴트 매개변수를 갖는 생성자
	~Dog();
	int getAge();
	void setAge(int 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개의 생성자가 있는 것과 같다. Dog() {age=1;} Dog(int a){age=a;}

20. 19번 소스 생성자의 정의를 클래스 밖에서 해보기

#include <iostream>
class Dog {
private:
	int age;
public:
	Dog(int a = 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;
}

 

 

C++ 강의 자료 참고했습니다.