B2024001225 윤지선
2학기 11주차 과제 본문



버츄얼 함수는 실행시간에 다형성을 구현하는 방법

# 함수 중첩 : 똑같은 이름의 함수를 여러개 만들 수 있다

#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;
}
함수중첩이 된 함수가 리턴값만 다른 것은 오류가 남
# 일반 괄호는 함수 다음에 쓴다
# 중괄호는 블럭을 만들 때 사용(for, if문)
# 대괄호는 배열을 쓸 때 사용
# 꺽쇠괄호는 자료형을 나중에 결정할 때 사용
#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;
}
함수 중첩을 하는 2가지 경우
1. 매개변수의 형이 다른 경우
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;
}

# 객체가 사라질때마다 소멸되는게 소멸자이기 때문에 10번 호출된다.


매우 중요!!
#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>
class Dog {
private:
int age; // 개의 나이를 저장하는 private 멤버 변수
public:
Dog(int a = 1) { age = a; } // 생성자: 기본값 1을 갖는 매개변수로 age 초기화
// 디폴트 매개변수를 갖는 생성자
~Dog(); // 소멸자 선언
int getAge(); // age 값을 반환하는 getter 메소드
void setAge(int a); // age 값을 설정하는 setter 메소드
};
Dog::~Dog()
{
std::cout << "소멸\n"; // 객체가 소멸될 때 "소멸" 출력
}
int Dog::getAge()
{
return age; // 현재 age 값 반환
}
void Dog::setAge(int a)
{
age = a; // 새로운 age 값 설정
}
int main()
{
Dog meri, happy(5); // meri는 기본 생성자로, happy는 age를 5로 초기화하여 생성
std::cout << happy.getAge() << "," <<
meri.getAge() << std::endl; // happy와 meri의 나이를 출력
return 0; // 프로그램 정상 종료
}
# 디폴트 인자와 함수 중첩은 똑같은 개념이라 둘 중 하나만 사용해야함.
#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;
}
int Hap(int i, int j, int k = 0, int l = 0)
{
return(i + j + k + l);
}

#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; }
~Dog() { std::cout << "bye~\n"; } //생성자(함수) 중첩
std::string getName() {return name;}
void setName(std::string n) {name = n;}
int getAge();
void setAge(int a);
};
int Dog::getAge() { return age; }
void Dog::setAge(int a) { age = a; }
int main()
{
Dog coco, happy(3, "해피");
//coco.setAge(1);
std::cout << coco.getName() <<coco.getAge()<< std::endl;
std::cout << happy.getName() << happy.getAge()<< std::endl;
return 0;
}

#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; }
~Dog() { std::cout << "bye~\n"; }
std::string getName() {return name;}
void setName(std::string n) {name = n;}
int getAge();
void setAge(int a);
};
int Dog::getAge() { return age; }
void Dog::setAge(int a) { age = a; }
int main()
{
Dog coco, happy(3, "해피");
//coco.setAge(1);
std::cout << coco.getName() <<coco.getAge()<< std::endl;
std::cout << happy.getName() << happy.getAge()<< std::endl;
return 0;
}
디폴트인자를 활용함. 실행결과는 위와 같음.
#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; }
~Dog() { std::cout << "bye~\n"; }
std::string getName();
void setName(std::string n);
int getAge();
void setAge(int a);
};
std::string Dog::getName() { return name; }
void Dog::setName(std::string n) { name = n; }
int Dog::getAge() { return age; }
void Dog::setAge(int a) { age = a; }
int main()
{
Dog coco, happy(3, "해피");
//coco.setAge(1);
std::cout << coco.getName() <<coco.getAge()<< std::endl;
std::cout << happy.getName() << happy.getAge()<< std::endl;
return 0;
}
함수를 클래스 밖으로 꺼냄.
#include <iostream>
class Dog {
private:
int age;
std::string name;
public:
// Dog() { age = 1; name = "강아지"; }
Dog(int a = 1, std::string n = "강아지");
~Dog();
std::string getName();
void setName(std::string n);
int getAge();
void setAge(int a);
};
Dog::Dog(int a, std::string n) { age = a; name = n; } //a=1과 n="강아지" 는 삭제해야함. 정의부에만 써야함
Dog::~Dog() { std::cout << "bye~\n"; }
std::string Dog::getName() { return name; }
void Dog::setName(std::string n) { name = n; }
int Dog::getAge() { return age; }
void Dog::setAge(int a) { age = a; }
int main()
{
Dog coco, happy(3, "해피");
//coco.setAge(1);
std::cout << coco.getName() <<coco.getAge()<< std::endl;
std::cout << happy.getName() << happy.getAge()<< std::endl;
return 0;
}
멤버 함수를 전부 클래스 밖에서 정의함. 실행결과는 동일.
#include <iostream>
class Dog {
private:
int age;
std::string name;
public:
// Dog() { age = 1; name = "강아지"; }
Dog(int a = 1, std::string n = "강아지");
~Dog();
std::string getName();
void setName(std::string n);
int getAge();
void setAge(int a);
};
Dog::Dog(int a, std::string n) { age = a; name = n; } //a=1과 n="강아지" 는 삭제해야함. 정의부에만 써야함
Dog::~Dog() { std::cout << "bye~\n"; }
std::string Dog::getName() { return name; }
void Dog::setName(std::string name) { this->name = name; }
int Dog::getAge() { return age; }
void Dog::setAge(int age) { this->age = age; }
int main()
{
Dog coco, happy(3, "해피");
//coco.setAge(1);
std::cout << coco.getName() <<coco.getAge()<< std::endl;
std::cout << happy.getName() << happy.getAge()<< std::endl;
return 0;
}
this 포인터 사용
#include <iostream>
class Dog {
private:
int age;
std::string name;
public:
// Dog() { age = 1; name = "강아지"; }
Dog(int a = 1, std::string n = "강아지");
~Dog();
std::string getName()const;
void setName(std::string n);
int getAge() const;
void setAge(int a);
};
Dog::Dog(int a, std::string n) { age = a; name = n; } //a=1과 n="강아지" 는 삭제해야함. 정의부에만 써야함
Dog::~Dog() { std::cout << "bye~\n"; }
std::string Dog::getName()const { return name; }
void Dog::setName(std::string name) { this->name = name; }
int Dog::getAge()const { return age; }
void Dog::setAge(int age) { this->age = age; }
int main()
{
Dog coco, happy(3, "해피");
//coco.setAge(1);
std::cout << coco.getName() <<coco.getAge()<< std::endl;
std::cout << happy.getName() << happy.getAge()<< std::endl;
return 0;
}
멤버변수를 변경하지 않은 함수들은 const로 지정하는게 좋음. getName과 getAge를 const로 지정함.
<chat gpt의 코드 설명>
- Dog 클래스 정의:
- private 멤버 변수: age(int), name(std::string)
- public 멤버 함수: 생성자, 소멸자, getter/setter 메서드들
- 생성자:
- Dog(int a = 1, std::string n = "강아지"): 디폴트 매개변수를 사용한 생성자
- 이 생성자는 기본 생성자와 매개변수를 받는 생성자의 역할을 모두 수행합니다.
- 소멸자:
- ~Dog(): 객체가 소멸될 때 "bye~" 메시지를 출력합니다.
- getter/setter 메서드:
- getName()과 getAge()는 const 메서드로 선언되어 객체의 상태를 변경하지 않음을 보장합니다.
- setName()과 setAge()에서는 this 포인터를 사용하여 매개변수와 멤버 변수를 구분합니다.
- 메서드 정의:
- 클래스 외부에서 각 메서드의 구현을 정의하고 있습니다.
- main() 함수:
- Dog coco: 기본 생성자 호출 (age=1, name="강아지")
- Dog happy(3, "해피"): 매개변수를 지정한 생성자 호출
- 두 객체의 이름과 나이를 출력합니다.
주요 특징:
- 디폴트 매개변수를 사용한 생성자로 여러 형태의 객체 생성을 지원합니다.
- const 메서드를 사용하여 객체의 상태 변경을 방지합니다.
- this 포인터를 사용하여 이름 충돌을 해결합니다.
- 클래스 선언과 정의를 분리하여 코드의 구조를 개선했습니다.
이 코드는 C++의 클래스, 생성자, 소멸자, 접근 제어, const 메서드, this 포인터 등 다양한 객체 지향 프로그래밍 개념을 보여주는 좋은 예시입니다.
'2024년 2학기 > C++ 프로그래밍' 카테고리의 다른 글
2학기 12주차 과제 (0) | 2024.11.18 |
---|---|
2학기 12주차 예습과제 (0) | 2024.11.18 |
2학기 11주차 예습과제 (0) | 2024.11.11 |
2학기 10주차 과제 (0) | 2024.11.04 |
2학기 10주차 예습과제 (4) | 2024.11.04 |