C++ 11주차

2023. 11. 15. 11:55💻 프로그래밍 언어/C++

객체지향언어의 3가지 특징

1. 캡슐화 (Encapsulation): 데이터와 그 데이터를 처리하는 함수를 하나의 '객체'라는 단위로 묶는 것. 이를 통해 데이터를 직접 조작하는 것이 아닌, 함수를 통해서만 데이터에 접근할 수 있게 함으로써 데이터의 안전성을 보장
2. 상속 (Inheritance): 기존의 클래스를 확장하여 새로운 클래스를 만드는 기능. 부모 클래스의 속성과 메소드를 자식 클래스가 물려받아 사용할 수 있게 하는 것으로, 코드의 재사용성을 높이고 유지 관리를 용이하게 한다.
3. 다형성(Polymorphism): 같은 이름의 메소드가 상황에 따라 다르게 동작하는 것. 이는 객체 간의 메시지 통신을 통일된 방식으로 처리할 수 있게 해주며, 코드의 유연성을 높인다.

 

function overloading을 지원하는 프로그래밍 언어

1. C++: C++은 함수 오버로딩을 지원하는 대표적인 언어입니다. 같은 이름의 함수를 여러 개 선언하고, 인자의 타입과 개수에 따라 다르게 동작하도록 할 수 있습니다.

#include<iostream>
using namespace std;

void func(int i) { 
    cout << "func(int i) called "; 
} 
  
void func(double d) { 
    cout << "func(double d) called "; 
} 

int main() { 
    func(10); // Calls func(int)
    func(10.5); // Calls func(double)
    return 0;
}


2. Java: Java 역시 함수 오버로딩을 지원합니다. 메소드 이름은 같게 하고, 매개변수의 타입이나 개수를 다르게 해서 여러 개의 메소드를 선언할 수 있습니다.

class Demo{
    void fun(int x){
        System.out.println("fun(int x) called");
    }
    void fun(double x){
        System.out.println("fun(double x) called");
    }
}

public class Main{
    public static void main(String[] args){
        Demo d = new Demo();
        d.fun(10); // Calls fun(int)
        d.fun(10.5); // Calls fun(double)
    }
}


3. C#: C#도 함수 오버로딩을 지원하는 언어입니다. 같은 이름의 메소드를 여러 개 선언하되, 매개변수의 타입이나 개수를 다르게 해서 사용할 수 있습니다.

using System;

class Program {
    static void Main() {
        fun(10); // Calls fun(int)
        fun(10.5); // Calls fun(double)
    }

    static void fun(int i) {
        Console.WriteLine("fun(int i) called");
    }

    static void fun(double d) {
        Console.WriteLine("fun(double d) called");
    }
}


4. Python: Python은 기본적으로 함수 오버로딩을 지원하지 않지만, 일부 라이브러리를 활용하거나 다른 방법을 사용하여 비슷한 효과를 낼 수 있습니다.

def fun(*args):
    for arg in args:
        if isinstance(arg, int):
            print("fun(int i) called")
        elif isinstance(arg, float):
            print("fun(double d) called")

fun(10) # Calls fun(int)
fun(10.5) # Calls fun(double)

함수 중첩 (function overloading)

디폴트 인자(default parameter)


다형성(polymorphism)

말 그대로 '여러 가지 형태'를 가질 수 있는 능력
C++에서 이는 특히 클래스와 관련된 개념으로, 상속 관계에 있는 클래스들이 같은 이름의 메서드를 가지면서도 각기 다른 동작을 할 수 있는 기능을 의미. C++의 다형성은 한 가지 타입의 포인터가 여러 가지 타입의 객체를 가리키게 해줘서, 같은 메서드 호출에도 다른 동작을 하게 할 수 있다. 

ex) 'Animal'이라는 부모 클래스가 있고, 'Dog', 'Cat' 등의 자식 클래스가 있다면, 'Animal' 타입의 포인터로 'Dog'와 'Cat' 객체를 가리키게 할 수 있다. 이렇게 되면 'Animal' 타입의 포인터를 통해 'speak()'라는 메서드를 호출하면, 실제 가리키고 있는 객체가 'Dog'면 '멍멍', 'Cat'이면 '야옹'이라는 소리를 내는 것처럼 동작할 수 있다.

 

다형성(polymorphism)의 종류

4p

 

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

버츄얼 펑션(virtual function)을 구현하는 것을 오버라이딩( overriding) 이라고 한다. 5p

 

함수오버로딩

이름이 같은 함수가 여러 개 있다.

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);
} //C++ function overloading

 

실습 6-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(int i, int j)
{
	return ((double)i + (double)j);
} //err, 매개변수가 일치하는 두 개의 함수는 오버로딩 할 수 없다.(시험에 냄)

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

Q: 위 소스가 에러가 나는 이유

A: 함수 오버로딩의 원칙에 어긋나기 때문
함수 오버로딩은 함수의 이름이 같더라도 매개변수의 타입 또는 개수가 다르면 다른 함수로 인식하는 기능인데, 여기서 중요한 점은 반환 타입이 다른 것만으로는 함수 오버로딩이 성립하지 않는다. 

 

실습 6-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;
}

 

다음 수업 미리보기

#include <iostream>
template <class T> T Max(T i, T 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;
}

 

실습 6-3: 함수중첩 : 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가지 경우

1. 매개변수의  다른 경우

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

 

실습 6-4: 생성자 중첩 예

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

파이썬 튜터

실습 6-5: 생성자 중첩 예

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

 

default parameter를 사용하는 프로그래밍 언어

default parameter: 함수를 호출할 때 특정 매개변수에 값을 제공하지 않으면, 그 매개변수가 기본값을 가지도록 하는 기능

1. C++: C++에서는 함수를 선언할 때 매개변수에 기본값을 지정할 수 있습니다.C++: C++에서는 함수를 선언할 때 매개변수에 기본값을 지정할 수 있습니다.

void displayMessage(std::string message, int times = 1) {
    for (int i = 0; i < times; i++) {
        std::cout << message << std::endl;
    }
}

int main() {
    displayMessage("Hello!");  // 함수 호출 시 두 번째 매개변수를 생략. 따라서 기본값인 1이 사용됨.
    return 0;
}

2 . Python: Python에서도 함수를 정의할 때 매개변수에 기본값을 지정할 수 있습니다.

def display_message(message, times=1):
    for i in range(times):
        print(message)

display_message("Hello!")  # 함수 호출 시 두 번째 매개변수를 생략. 따라서 기본값인 1이 사용됨.


3. Java: Java는 기본 매개변수를 직접 지원하지 않습니다. 하지만 메서드 오버로딩을 이용하여 비슷한 효과를 낼 수 있습니다.

public class Main {
    void displayMessage(String message) {
        displayMessage(message, 1);
    }

    void displayMessage(String message, int times) {
        for (int i = 0; i < times; i++) {
            System.out.println(message);
        }
    }

    public static void main(String[] args) {
        Main main = new Main();
        main.displayMessage("Hello!");  // 함수 호출 시 두 번째 매개변수를 생략. 따라서 오버로드된 메서드에서 기본값인 1이 사용됨.
    }
}


4. JavaScript: JavaScript에서는 함수를 선언할 때 매개변수에 기본값을 지정할 수 있습니다.

function displayMessage(message, times = 1) {
    for (let i = 0; i < times; i++) {
        console.log(message);
    }
}

displayMessage("Hello!");  // 함수 호출 시 두 번째 매개변수를 생략. 따라서 기본값인 1이 사용됨.

 

실습 6-7: 디폴트 인자

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

▶ C++에서는 함수를 호출할 때 별도의 매개변수를 전달하지 않아도 기본적인 값을 전달하도록 함수 원형을 선언할 때 디폴트 값을 지정할 수 있다.

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

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

#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()함수 전에 함수 선언을 하면 선언부에만 디폴트 인자를 지정해야 한다.

실습 6-8: 디폴트 인자를 갖는 생성자

#include <iostream>
class Dog {
private:
	int age;
public:
	Dog(int a = 0) { age = a; }
	//Dog() { age = 0;  }
	// 디폴트 매개변수를 갖는 생성자
	~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;
}

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

#include <iostream>
class Dog {
private:
	int age;
public:
	Dog(int a = 0);
	//Dog() { age = 0;  }
	// 디폴트 매개변수를 갖는 생성자
	~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;
} //main()함수 전에 함수 선언을 하면 선언부에만 디폴트 인자를 지정해야 한다.

실습 6-9: 디폴트 인자 응용

#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++ 프로그래밍 강의자료

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

C++ 13주차  (1) 2023.11.29
C++ 12주차  (0) 2023.11.22
C++ 10주차  (0) 2023.11.08
C++ 9주차  (0) 2023.11.01
C++ 6주차  (1) 2023.10.18