B2024001225 윤지선

2학기 11주차 과제 본문

2024년 2학기/C++ 프로그래밍

2학기 11주차 과제

윤지선 2024. 11. 11. 16:20

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

 

 

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

 

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

 

함수 이름이 똑같지만 알아서 잘 찾아감(?)

 

#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의 코드 설명>

  1. Dog 클래스 정의:
    • private 멤버 변수: age(int), name(std::string)
    • public 멤버 함수: 생성자, 소멸자, getter/setter 메서드들
  2. 생성자:
    • Dog(int a = 1, std::string n = "강아지"): 디폴트 매개변수를 사용한 생성자
    • 이 생성자는 기본 생성자와 매개변수를 받는 생성자의 역할을 모두 수행합니다.
  3. 소멸자:
    • ~Dog(): 객체가 소멸될 때 "bye~" 메시지를 출력합니다.
  4. getter/setter 메서드:
    • getName()과 getAge()는 const 메서드로 선언되어 객체의 상태를 변경하지 않음을 보장합니다.
    • setName()과 setAge()에서는 this 포인터를 사용하여 매개변수와 멤버 변수를 구분합니다.
  5. 메서드 정의:
    • 클래스 외부에서 각 메서드의 구현을 정의하고 있습니다.
  6. 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