C++
11. 함수 중첩, 디폴트 인자
리버윤
2024. 11. 12. 11:01
728x90
Chat gpt. 객체지향언어의 4가지 대표적인 특징을 알려줘
- 캡슐화 (Encapsulation) : 데이터와 그 데이터를 처리하는 메서드를 하나의 단위로 묶어 외부에서 직접 접근하지 못하도록 보호하는 개념입니다. 이를 통해 데이터의 안전성을 높이고, 코드의 유지보수를 용이하게 합니다.
- 상속 (Inheritance) : 기존 클래스(부모 클래스)의 속성과 메서드를 새로운 클래스(자식 클래스)가 물려받는 기능입니다. 이를 통해 코드의 재사용성을 높이고, 계층 구조를 만들 수 있습니다.
- 다형성 (Polymorphism) : 동일한 인터페이스를 통해 서로 다른 클래스의 객체를 처리할 수 있는 능력입니다. 메서드 오버로딩과 메서드 오버라이딩을 통해 구현되며, 프로그램의 유연성을 증가시킵니다.
- 추상화 (Abstraction) : 복잡한 시스템에서 필요한 부분만을 모델링하여 단순화하는 과정입니다. 객체의 속성과 행동을 정의하고, 불필요한 세부 사항은 감추어 사용자가 쉽게 이해하고 사용할 수 있도록 합니다.
프로그래밍 언어에서 (), {}, [], <> 의 용도를 알려줘
- ( ) (괄호) : 함수 호출 시 매개변수를 전달할 때 사용합니다. 예: functionName(arg1, arg2).
수학적 표현의 우선순위를 지정할 때 사용합니다. 예: result = (a + b) * c.
조건문이나 반복문에서 조건을 그룹화할 때도 사용합니다. 예: if (condition) { ... }. - { } (중괄호) : 코드 블록을 정의하는 데 사용합니다. 예를 들어, 함수, 조건문, 반복문의 몸체를 감쌀 때 사용합니다. 예: if (condition) { ... }.
객체 리터럴을 정의할 때도 사용됩니다. 예: let obj = { key: value };.
클래스 정의 시에도 사용됩니다. 예: class MyClass { ... };. - [ ] (대괄호) : 배열이나 리스트를 정의하고 접근할 때 사용합니다. 예: array[index].
리스트, 벡터 등 다양한 자료구조를 표현하는 데 사용됩니다. 예: std::vector<int> vec;.
인덱스 연산자를 사용할 때도 사용됩니다. 예: list[0] = value;. - < > (각괄호) : 제네릭 타입을 정의할 때 사용합니다. 예: List<String> list;.
HTML/XML과 같은 마크업 언어에서 태그를 정의할 때 사용됩니다. 예: <tag>content</tag>.
C++ 템플릿 인스턴스화 시에도 사용됩니다. 예: template<typename T> class MyClass;.
- C++에서 다형성의 종류
1. 함수 오버로딩(중첩, function overloading)
- 다형성을 구현하는 한가지 방법
- 하나의 함수명을 여러 개의 유사 목적으로 사용할 수 있다.
- C의 경우 함수 중첩 불가능
- 함수 중첩 예제
#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;
}
ctrl + m + o :코드 접기
ctrl + m + l : 코드 펼치기
- 매개변서의 형이 다른 오버로딩
#include <iostream>
int Max(int i, int j) //소문자 max는 이미 있는거라 대문자로
{
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>
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가지 경우
- 매개변수의 형이 다른 경우
- 매개변수의 개수가 다른 경우
▶ 생성자 중첩
- 클래스의 멤버함수도 중첩이 가능하고, 생성자도 물론 중첩 가능
- But, 소멸자는 중첩 불가능
- 생성자에 함수를 중첩시키는 것은 객체에 초기값을 다양하게 주는 선택 기회를 제공하는 것
- 1단계
#include <iostream>
class Dog { //1단계
};
int main()
{
return 0;
}
- 2단계
#include <iostream>
class Dog { //1단계, class 생성
private:
int age; //2단계, 멤버변수 만들기
};
int main()
{
return 0;
}
- 3단계
#include <iostream>
class Dog { //1단계, class 생성
private:
int age; //2단계, 멤버변수 만들기
public:
getAge() {
}
setAge() {
} // 3단계, 입출력함수 만들기
};
int main()
{
return 0;
}
- 4단계
#include <iostream>
class Dog { //1단계, class 생성
private:
int age; //2단계, 멤버변수 만들기
public:
int getAge() {
return age;
}
void setAge(int a) {
age = a;
} // 3단계, 입출력함수 만들기
};
int main()
{
return 0;
}
- 5단계
#include <iostream>
class Dog { //1단계, class 생성
private:
int age; //2단계, 멤버변수 만들기
public:
int getAge() {
return age;
}
void setAge(int a) {
age = a;
} // 3단계, 입출력함수 만들기
};
int main()
{
Dog coco;
std::cout << coco.getAge(); // 쓰레기값 출력됨
return 0;
}
- 6단계
#include <iostream>
class Dog { //1단계, class 생성
private:
int age; //2단계, 멤버변수 만들기
public:
int getAge() {
return age;
}
void setAge(int a) {
age = a;
} // 3단계, 입출력함수 만들기
};
int main()
{
Dog coco;
coco.setAge(3); //나이 입력하고 출력
std::cout << coco.getAge(); // 쓰레기값 출력됨
return 0;
}
- 7단계 (생성자)
#include <iostream>
class Dog { //1단계, class 생성
private:
int age; //2단계, 멤버변수 만들기
public:
int getAge() {
return age;
}
void setAge(int a) {
age = a;
} // 3단계, 입출력함수 만들기
Dog() { //생성자. 클래스 이름과 같음
}
};
int main()
{
Dog coco;
coco.setAge(3); //나이 입력하고 출력
std::cout << coco.getAge(); // 쓰레기값 출력됨
return 0;
}
- 8단계
#include <iostream>
class Dog { //1단계, class 생성
private:
int age; //2단계, 멤버변수 만들기
public:
int getAge() {
return age;
}
void setAge(int a) {
age = a;
} // 3단계, 입출력함수 만들기
Dog() { //생성자. 클래스 이름과 같음
age = 1;
}
};
int main()
{
Dog coco;
//coco.setAge(3); //나이 입력하고 출력
std::cout << coco.getAge(); // 1출력
return 0;
}
- 9단계
#include <iostream>
class Dog {
private:
int age;
public:
int getAge() {
return age;
}
void setAge(int a) {
age = a;
}
Dog() { //생성자. 클래스 이름과 같음
age = 1;
}
Dog(int a) { //생성자 함수 중첩
age = a;
}
};
int main()
{
Dog coco, happy(5);
//coco.setAge(3); //나이 입력하고 출력
std::cout << coco.getAge() << std::endl;
std::cout << happy.getAge() << std::endl;
return 0;
}
- 10단계(소멸자)
#include <iostream>
class Dog {
private:
int age;
public:
int getAge() {
return age;
}
void setAge(int a) {
age = a;
}
Dog() {
age = 1;
}
Dog(int a) {
age = a;
}
~Dog() { //소멸자, 종료되면서 자동으로 출력
std::cout << "bye~~ \n";
}
};
int main()
{
Dog coco, happy(5);
//coco.setAge(3); //나이 입력하고 출력
std::cout << coco.getAge() << std::endl;
std::cout << happy.getAge() << std::endl;
return 0;
}
- 11단게
#include <iostream>
class Dog {
private:
int age;
public:
int getAge() { return age; }
void setAge(int a) { age = a; }
Dog() { age = 1; }
Dog(int a) { age = a; }
~Dog() { std::cout << "bye~~ \n"; }
};
//밖으로 끄집어내기
int Dog::getAge() { return age; }
void Dog::setAge(int a) { age = a; } //Dog:: 위치 주의
Dog::Dog() { age = 1; }
Dog::Dog(int a) { age = a; }
Dog::~Dog() { std::cout << "bye~~ \n"; }
int main()
{
Dog coco, happy(5);
//coco.setAge(3); //나이 입력하고 출력
std::cout << coco.getAge() << std::endl;
std::cout << happy.getAge() << std::endl;
return 0;
}
- 12단계
#include <iostream>
class Dog {
private:
int age;
public:
int getAge();
void setAge(int a);
Dog(); //생성자
Dog(int a); //생성자
~Dog(); //소멸자
};
//밖으로 끄집어내기
int Dog::getAge() { return age; }
void Dog::setAge(int a) { age = a; } //Dog:: 위치 주의
Dog::Dog() { age = 1; }
Dog::Dog(int a) { age = a; }
Dog::~Dog() { std::cout << "bye~~ \n"; }
int main()
{
Dog coco, happy(5);
//coco.setAge(3); //나이 입력하고 출력
std::cout << coco.getAge() << std::endl;
std::cout << happy.getAge() << std::endl;
return 0;
}
- 생성자 중첩 예
#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;
}
2. 디폴트 인자(default parameter, default argument)
- 디폴트 매개변수
- C++에서는 함수를 호출할 때 별도의 매개변수를 전달하지 않아도 기본적인 값을 전달하도록 함수 원형을 선언할 때 디폴트 값을 지정할 수 있다.
- 디폴트 매개변수의 사용은 함수 중첩을 축약형
- 디폴트 매개변수를 정의하기 시작하면 그 다음의 매개변수들은 모두 디폴트 매개변수를 기져야 함
- int add(int i=1, int j=2);
- int add(int i, int j=2); //이건 가능
- int add(int i=1, int j); //오류 발생
#include <iostream>
int add(int i, 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) // 형식매개변수, 2개가 넘어와야하는데 안넘어온다면 저 값을 쓰겠다는 것
{
return(i + j);
}
int main()
{
std::cout << add() << ","; // 실매개변수 없음, 3
std::cout << add(10) << ","; // 실매개변수 한 개, 12
std::cout << add(10, 20); // 실매개변수 두개, 30
return 0;
}
2개가 넘어와야하는데 안넘어온다면 저 값을 쓰겠다는 것
#include <iostream>
int add(int i, int j=1) // 형식매개변수
{
return(i + j);
}
int main()
{
//std::cout << add() << ","; // 실매개변수 없음,
std::cout << add(10) << ","; // 실매개변수 한 개, 11
std::cout << add(10, 20); // 실매개변수 두개, 30
return 0;
}
※ 선언과 정의를 나눴을 때는 선언부에만 디폴트 값 작성. 정의부에는 작성하지 않는다.
#include <iostream>
int add(int i = 1, int j = 2); //선언, 선언부에만 디폴트 작성
int main()
{
//std::cout << add() << ","; // 실매개변수 없음,
std::cout << add(10) << ","; // 실매개변수 한 개, 11
std::cout << add(10, 20); // 실매개변수 두개, 30
return 0;
}
int add(int i, int j) //정의
{
return(i + j);
}
-
#include <iostream>
class Dog {
private:
int age;
public:
int getAge();
void setAge(int a);
//Dog();
//Dog(int a);
~Dog();
Dog(int a=1) { age = a; }
};
int Dog::getAge() { return age; }
void Dog::setAge(int a) { age = a; } //Dog:: 위치 주의
//Dog::Dog() { age = 1; }
//Dog::Dog(int a) { age = a; }
Dog::~Dog() { std::cout << "bye~~ \n"; }
int main()
{
Dog coco, happy(5);
//coco.setAge(3); //나이 입력하고 출력
std::cout << coco.getAge() << std::endl;
std::cout << happy.getAge() << std::endl;
return 0;
}
#include <iostream>
class Dog {
private:
int age;
public:
int getAge();
void setAge(int a);
//Dog();
//Dog(int a);
~Dog();
Dog(int a = 1); //디폴드 값은 여기 선언에만 작성
};
int Dog::getAge() { return age; }
void Dog::setAge(int a) { age = a; } //Dog:: 위치 주의
//Dog::Dog() { age = 1; }
//Dog::Dog(int a) { age = a; }
Dog::~Dog() { std::cout << "bye~~ \n"; }
Dog::Dog(int a) { age = a; }
int main()
{
Dog coco, happy(5);
//coco.setAge(3); //나이 입력하고 출력
std::cout << coco.getAge() << std::endl;
std::cout << happy.getAge() << std::endl;
return 0;
}
- 총 예제
- 1단계
#include <iostream>
class Dog {
private:
int age;
std::string name;
public:
int getAge() { return age; }
void setAge(int a) { age = a; }
};
int main()
{
return 0;
}
-2단계
#include <iostream>
class Dog {
private:
int age;
std::string name;
public:
int getAge() { return age; }
void setAge(int a) { this -> age = age; }
std::string getName() { return name; }
void setName(std::string n) { this -> name = name; }
};
int main()
{
return 0;
}
- 3단계
#include <iostream>
class Dog {
private:
int age;
std::string name;
public:
int getAge() { return age; }
void setAge(int age) { this -> age = age; }
std::string getName() { return name; }
void setName(std::string name) { this -> name = name; }
};
int main()
{
Dog coco;
coco.setName("코코");
coco.setAge(1);
std::cout << coco.getName() << coco.getAge();
return 0;
}
-4단계 (생성자)
#include <iostream>
class Dog {
private:
int age;
std::string name;
public:
Dog() { //생성자
age = 1;
name = "강아지";
} //세미콜론 주의
int getAge() { return age; }
void setAge(int age) { this -> age = age; }
std::string getName() { return name; }
void setName(std::string name) { this -> name = name; }
};
int main()
{
Dog coco, happy;
std::cout << coco.getName() << coco.getAge() << std::endl; //강아지 1
std::cout << happy.getName() << happy.getAge() << std::endl; //강아지 1
coco.setName("코코");
coco.setAge(1);
std::cout << coco.getName() << coco.getAge() << std::endl; // 코코 1
std::cout << happy.getName() << happy.getAge() << std::endl; //강아지 1
return 0;
}
-5단계
#include <iostream>
class Dog {
private:
int age;
std::string name;
public:
Dog() { //생성자
age = 1;
name = "강아지";
} //세미콜론 주의
Dog(int a, std::string n) { //생성자, 함수중첩
age = a;
name = n;
}
int getAge() { return age; }
void setAge(int age) { this -> age = age; }
std::string getName() { return name; }
void setName(std::string name) { this -> name = name; }
};
int main()
{
Dog coco, happy(3, "해피");
std::cout << coco.getName() << coco.getAge() << std::endl; //강아지 1
std::cout << happy.getName() << happy.getAge() << std::endl; //해피 3
coco.setName("코코");
coco.setAge(1);
std::cout << coco.getName() << coco.getAge() << std::endl; // 코코 1
std::cout << happy.getName() << happy.getAge() << std::endl; //해피3
return 0;
}
- 6단계
#include <iostream>
class Dog {
private:
int age;
std::string name;
public:
/*Dog() { //생성자
age = 1;
name = "강아지";
} */
Dog(int a=1, std::string n="강아지") { //디폴트 인자를 갖는 생성자
age = a;
name = n;
}
int getAge() { return age; }
void setAge(int age) { this -> age = age; }
std::string getName() { return name; }
void setName(std::string name) { this -> name = name; }
};
int main()
{
Dog coco, happy(3, "해피");
std::cout << coco.getName() << coco.getAge() << std::endl; //강아지 1
std::cout << happy.getName() << happy.getAge() << std::endl; //해피 3
coco.setName("코코");
coco.setAge(1);
std::cout << coco.getName() << coco.getAge() << std::endl; // 코코 1
std::cout << happy.getName() << happy.getAge() << std::endl; //해피3
return 0;
}
-7단계
#include <iostream>
class Dog {
private:
int age;
std::string name;
public:
/*Dog() { //생성자
age = 1;
name = "강아지";
} */
Dog(int age=1, std::string name="강아지") { //디폴트 인자를 갖는 생성자
this->age = age;
this->name = name;
}
int getAge() { return age; }
void setAge(int age) { this -> age = age; }
std::string getName() { return name; }
void setName(std::string name) { this -> name = name; }
};
int main()
{
Dog coco, happy(3, "해피");
std::cout << coco.getName() << coco.getAge() << std::endl; //강아지 1
std::cout << happy.getName() << happy.getAge() << std::endl; //해피 3
coco.setName("코코");
coco.setAge(1);
std::cout << coco.getName() << coco.getAge() << std::endl; // 코코 1
std::cout << happy.getName() << happy.getAge() << std::endl; //해피3
return 0;
}
-8단계 (const 추가)
#include <iostream>
class Dog {
private:
int age;
std::string name;
public:
/*Dog() { //생성자
age = 1;
name = "강아지";
} */
Dog(int age=1, std::string name="강아지") { //디폴트 인자를 갖는 생성자
this->age = age;
this->name = name;
}
int getAge() const { return age; }
void setAge(int age) { this -> age = age; }
std::string getName() const { return name; }
void setName(std::string name) { this -> name = name; }
};
int main()
{
Dog coco, happy(3, "해피");
std::cout << coco.getName() << coco.getAge() << std::endl; //강아지 1
std::cout << happy.getName() << happy.getAge() << std::endl; //해피 3
coco.setName("코코");
coco.setAge(1);
std::cout << coco.getName() << coco.getAge() << std::endl; // 코코 1
std::cout << happy.getName() << happy.getAge() << std::endl; //해피3
return 0;
}
- 최종 밖으로 빼내는 수정
#include <iostream> // 입출력 스트림 라이브러리 포함
class Dog { // Dog 클래스를 정의
private:
int age; // 개의 나이를 저장하는 private 변수
std::string name; // 개의 이름을 저장하는 private 변수
public:
// 기본 매개변수를 갖는 생성자 선언
Dog(int age = 1, std::string name = "강아지");
int getAge() const; // 나이를 반환하는 메서드 선언
void setAge(int age); // 나이를 설정하는 메서드 선언
std::string getName() const; // 이름을 반환하는 메서드 선언
void setName(std::string name); // 이름을 설정하는 메서드 선언
};
// 생성자 정의: 기본 매개변수 사용
Dog::Dog(int age, std::string name) {
this->age = age; // 매개변수 age를 클래스의 age 변수에 할당
this->name = name; // 매개변수 name을 클래스의 name 변수에 할당
}
int Dog::getAge() const { return age; } // 나이를 반환하는 메서드 구현
void Dog::setAge(int age) { this->age = age; } // 나이를 설정하는 메서드 구현
std::string Dog::getName() const { return name; } // 이름을 반환하는 메서드 구현
void Dog::setName(std::string name) { this->name = name; } // 이름을 설정하는 메서드 구현
int main() // 프로그램의 시작점
{
Dog coco; // 기본 생성자를 사용하여 coco 객체 생성 (age=1, name="강아지")
Dog happy(3, "해피"); // 매개변수를 사용하여 happy 객체 생성 (age=3, name="해피")
// coco 객체의 이름과 나이를 출력 (강아지 1)
std::cout << coco.getName() << coco.getAge() << std::endl;
// happy 객체의 이름과 나이를 출력 (해피 3)
std::cout << happy.getName() << happy.getAge() << std::endl;
coco.setName("코코"); // coco 객체의 이름을 "코코"로 변경
coco.setAge(1); // coco 객체의 나이를 1로 설정 (변경 없음, 이미 1)
// coco 객체의 이름과 나이를 출력 (코코 1)
std::cout << coco.getName() << coco.getAge() << std::endl;
// happy 객체의 이름과 나이를 출력 (해피 3)
std::cout << happy.getName() << happy.getAge() << std::endl;
return 0; // 프로그램 정상 종료
}
728x90