// 숙제
/// > CharacterJob을 상속 받은 Warrior와 Mage를 만듭니다.

// -- output --
/// > 직업 : 전사
/// > 무기 : 대검
/// > 방어력 : 10
/// > 직업 : 마법사
/// > 무기 : 두터운 지팡이
/// > 마력 : 15
#include <iostream>
using namespace std;

namespace Enum
{
	enum Job
	{
		Warrior, Mage
	};
	
	enum Weapon
	{
		대검, 지팡이
	};
}

class CharacterJob
{
private:
	Enum::Job job;
	Enum::Weapon weapon;

public:
	void SetCharacterJobInfo(Enum::Job job, Enum::Weapon weapon)
	{
		this->job = job;
		this->weapon = weapon;
	}

	void PrintCharacterJobInfo()
	{
		cout << "직업 : " << ((job == Enum::Job::Warrior) ? "전사" : "마법사") << endl;
		cout << "무기 : " << ((weapon == Enum::Weapon::대검) ? "대검" : "두터운 지팡이") << endl;
	}
};

class Warrior : public CharacterJob
{
private:
	int defence;

public:
	void SetWarriorInfo(Enum::Job job, Enum::Weapon weapon, int defence)
	{
		SetCharacterJobInfo(job, weapon);
		this->defence = defence;
	}

	void PrintWarriorInfo()
	{
		PrintCharacterJobInfo();
		cout << "방어력 : " << defence << endl;
	}
};

class Mage : public CharacterJob
{
private:
	int mp;

public:
	void SetMageInfo(Enum::Job job, Enum::Weapon weapon, int mp)
	{
		SetCharacterJobInfo(job, weapon);
		this->mp = mp;
	}

	void PrintMageInfo()
	{
		PrintCharacterJobInfo();
		cout << "마력 : " << mp << endl;
	}
};

int main()
{
	Warrior* player1 = new Warrior();
	player1->SetWarriorInfo(Enum::Warrior, Enum::대검, 10);
	player1->PrintWarriorInfo();

	Mage* player2 = new Mage();
	player2->SetMageInfo(Enum::Mage, Enum::지팡이, 15);
	player2->PrintMageInfo();

	delete player1;
	player1 = nullptr;
	delete player2;
	player2 = nullptr;


	return 0;
}

 

내가 밤새서 만들어간 코드

지금은 무기 2가지, 직업 2가지라 열거형으로도 괜찮았지만 그 이상으로 늘었을 때 열거형은 힘들 수 있다고 하셨다.

부족함이 많지만 그래도 내 힘으로 혼자 해낸 코드 중 하나이다...

값져...ㅠㅠㅠㅠㅠㅠㅠ

밤새서 했는데 정말 다행이다.

 

처음에는 player->SetWarriorInfo(Warrior, 대검, 10); 해서 방어력(, 마력)이 출력이 안됐었는데 Enum 안에 있는 Warrior와 대검임을 Enum::으로 지정해주니 드디어 됐다!

또, CharacterJob player = new CharacterJob();이 아닌 Warrior와 Mage로 각각 객체생성? 해줘야 한다.

player도 구분해야 한다고 하셔서 1,2를 붙여봤는데 이게 맞겠지?

자료형 bool

#include <iostream>
using namespace std;

bool IsRight(int num)
{
    if(num <= 0)
    	return false;
    else
    	return true;
}

int main()
{
    bool isRig;
    int num;
    cout << "Input number : ";
    cin >> num;  // 숫자 입력받음
    
    isRig = IsRight(num);
    if (isRig)  // bool형은 조건문에 true인지 false 쓰지 않아도 기본적으로 true 다는 전제
    	cout << "Right number" << endl;  // true면 출력
    else
    	cout << "Wrong number" << endl;  // false면 출력
        
    return 0;
}

클래스는 메모리가 없다. 따라서 클래스는 참조할 수 없다. 그래서 main에서 동적할당해주나?

클래스 상속은 참조가 아니라 컴파일 단계에서 부모클래스를 호출하는 것 뿐.

부모클래스의 생성자는 자식한테 상속되지 않는다.

// 클래스 이름 : AirConditioner
// 변수
/// 전원 On/Off 변수
/// 온도 저장 변수
/// 전원 초기 값 : 꺼짐
/// 온도 초기 값 : 22'C
// 메서드
/// 전원 On/Off
/// 온도 설정
/// 온도 증가
/// 온도 감소
/// 현재 온도 출력
// main
/// 전원 On
/// 18도로 설정
/// 현재 온도 출력
/// 온도 증가
/// 현재 온도 출력
/// 온도 감소
/// 현재 온도 출력
/// 전원 Off

온도 temp, 온도 출력, 전원, 온도증감 4개 만들기

#include <iostream>
using namespace std;

typedef unsigned int uint;

class AirConditioner
{
private:
	bool isPower = false;		// 초기값 Off
	uint temp = 22;			// 초기값 22도

public:
	AirConditioner(uint temp)	// 온도
	{
		this->temp = temp;
	}
	
	void PrintTemp()		// 온도 출력
	{
		cout << "현재 온도 : " << temp << endl;
	}

	void PowerOnOff(bool isPower)	// 전원
	{
		this->isPower = isPower;
		cout << "전원을 " << ((this->isPower == true) ? "켭니다." : "끕니다") << endl;
	}
	
	void TempUpDown(bool isUp)	// 온도 증감, 참이면 증가, 거짓이면 감소
	{
		if (isUp)
		{
			temp++;
			cout << "온도를 올립니다." << endl;
			PrintTemp();
		}
		else
		{
			temp--;
			cout << "온도를 내립니다." << endl;
			PrintTemp();
		}
	}
};

int main()
{
	AirConditioner* aircon = new AirConditioner(18);	// 18로 변수 초기화
	//aircon은 변수, AirConditioner은 생성자, new는 동적메모리 할당 키워드
	//aircon 포인터가 new AirConditioner라는 동적메모리를 참조함
	//Airconditioner크기만큼의 동적 메모리를 할당받아 aircon포인터에 담아 사용하겠다
	//(클래스는 참조형식, 구조체는 값형식)
	//클래스의 정보전달은 AirConditioner이라는 생성자가 함
	aircon->PowerOnOff(true);
	aircon->TempUpDown(true);
	aircon->TempUpDown(false);
	aircon->PowerOnOff(false);

	return 0;
}

 

화면 전체공유로 검사 받았던 과제..

난 못 풀었고 굉장히 쪽팔렸던 과제..

그래서 밤새 포인터 공부를 했다..

분명 쉬워보이는데..

그런데도 정확히 모르겠어 엿먹어 포인터!

1. 정적할당 : 처음부터 끝까지 메모리를 들고 있는 것

2. 동적할당 : 개발자가 런타임 도중 원할 때 메모리를 할당하고 해제해주는 것

 

3. 포인터

: 변수의 주소를 저장하는 변수. (변수의 주소가 저장됨)

 

포인터는 변수a의 (메모리 공간의) 주소(200번)가 포인터에 저장된다.(200) 이 포인터는 해당 주소의 변수를 가리키고 그 변수 안에 값(5)이 저장되어 있다.

 

가리킬 변수의 자료형을 포인터 앞에 적어 선언한다.

 

<C에서 포인터>

#include <stdio.h>

int main()
{
	int a = 5;
	int *ptr_a; // 여기서 *는 포인터를 선언하기 위해 붙음
	ptr_a = &a; // &는 주소를 뜻함. 만약 주소를 200이라면

	printf("ptr_a에 저장된 값 : %d\n", ptr_a); // 200 출력
	printf("ptr_a가 가리키는 변수의 값 : %d\n", *ptr_a); // 5 출력. 여기서 *는 역참조?로 a 값 출력
	
	*ptr_a = 10; // ptr_a가 가리키는 변수의 값이 5에서 10으로 변경됨
	printf("ptr_a가 가리키는 변수의 값 : %d\n", *ptr_a); // 10
	printf("ptr_a가 가리키는 변수의 값 : %d\n", a); // 둘 다 같음. 10
    
    return 0;
}

프린트문에 *ptr_a는 역참조인가??

*(역참조) : (포인터로 가리킨) 해당 주소에 저장된 값?

 

#include <stdio.h>

// 각각 주소 임의로 설정함

int main()
{
    int a = 5;
    
    int *ptr;
    ptr = &a;
    
    int **ptr_ptr; // *(*ptr_ptr)과 같은듯?
    ptr_ptr = &ptr;
    
    printf("a = %d\n", a);   // 값 5
    printf("&a = %d\n", &a); // 주소 200
    
    printf("ptr = %d\n", ptr); // 값 200
    printf("&ptr = %d\n", &ptr); // 주소 300
    
    printf("ptr_ptr = %d\n", ptr_ptr); // 값 300
    printf("&ptr_ptr = %d\n", &ptr_ptr); // 주소 500
    printf("*ptr_ptr = %d\n", *ptr_ptr); // 값 200
    printf("**ptr_ptr = %d\n", **ptr_ptr); // 값 5
    
    return 0;
}

하 이건가..?

 

#include <stdio.h>

int main()
{
    int numArr[5] = { 11, 22, 33, 44, 55 };
    int *numPtrA; // *는 포인터 numPtrA를 선언하기 위함. 주소값
    //int *numPtrB;
    //int *numPtrC;
    
    numPtrA = numArr; // 배열의 첫번째 주소(numArr[0])?는 numArr다?
    
    //numPtrB =numPtrA + 1; // 주소 한칸씩 옆으로 옮기기, numArr[1] 주소?와 같음
    //numPtrC =numPtrA + 2; // numArr[2]와 같음
    
    //printf("%d\n", *numPtrB); // 22, *numPtrB는 numArr[1]값과 같음
    //printf("%d\n", *numPtrC); // 33, numArr[2]값
    printf("%d\n", *(numPtrA + 1)); // 22
    printf("%d\n", *(numPtrA + 2)); // 33
    printf("%d\n", *numPtrA + 1); // 12
    
    return 0;
}

 

<C++에서 포인터>

#include <iostream>
using namespace std;

int main()
{
    int *a = new int(5);	// *a는 int를 가르키는 포인터
    // (int)메모리 상의 공간에 5라는 값이 담기고 이 메모리의 주소가 200이라면 (메모리 할당)
    // 주소값 200을 a가 담고, 포인터 *a는 주소 200 안에 담긴 값 5를 가르킴
    
    cout << a << endl;	// 주소값 출력. 200
    cout << *a << endl;	// 실제로 저장된 값 출력. 5
    
    *a = 10; // 5가 저장된 걸 10으로 바꿔라
    
    cout << a << endl;	// 주소값 출력. 200
    cout << *a << endl;	// 실제로 저장된 값 출력. 10
    
    delete a;	// 할당했던 메모리가 해제되어 낭비가 되지 않음
}

200번지 메모리공간을 포인터 *a가 가르킴  

 

1. 함수 오버로딩

: (C는 안되지만 C++에선)함수의 이름이 같을 때, 함수호출 시 매개변수의 자료형, 개수가 다르면 호출하고자 하는 함수의 구분 가능해 사용할 수 있다.

반환형만 다르고 같은 이름의 함수는 오버로딩이 불가능하다.

1. 객체지향 프로그래밍 언어의 3대 특성
/// > 은닉성(캡슐화) : 코드에 대한 보안을 지키기위해 멤버의 접근여부를 판별함 
/// > 상속성
/// > 다형성 : 같은 타입의 객체가 각각 다른 결과를 가질 수 있는 속성

 

2. 접근제한자

C++의 기본 접근제한자는 private, 클래스 외부에서 접근이 불가능하다.

#include <iostream>
using namespace std;

class Student
{
public:
	enum Gender 
	{
		Man,Woman
	};

private:
	const char* name;	
	int age;
	Gender gender;

public: //메모리가 존재하지 않는 메서드로 값만 반환함
	//Getter / 접근자
	const char* GetName() //은닉성으로 나까지 접근 못할때 편법으로 뚫어줌, name의 메모리가 아닌 값만 반환됨
	{
		return name;
	}

	int GetAge()
	{
		return age;
	}

	//Setter / 설정자
	void SetStudentInfo(const char* name, int age, Gender gender)
	{
		this->name = name;
		this->age = age;	//this포인터는 자기자신
		this->gender = gender;
	}

	// 함수 뒤에 const : 해당 함수 내부에서 멤버에 대한 값 설정이 일어나지 않겠다.
	void PrintStudentInfo() const
	{
		cout << "이름 : " << name << endl;
		cout << "나이 : " << age << endl;
		cout << "성별 : " << ((gender == Gender::Man) ? "남자" : "여자") << endl;
	}
};

int main()
{
	Student* student = new Student();
	student->SetStudentInfo("김방방", 2, Student::Gender::Man);
	//student->PrintStudentInfo(); // 이름, 나이, 성별 전체 출력

	// 이름만 출력하고 싶은데 private이면 Getter를 이용해 메모리 없는 name값만 반환함
	cout << student->GetName() << endl;
	//cout << student->GetAge() << endl; //age도 age만 출력 가능


	delete student;
	student = nullptr;


	return 0;
}

 

3. TextGame

함수쓸 때 처음에는 void로 했다가 다 쓰고 맞는 반환 형식으로 고치기

 

void SetHp(int hp) { this->hp = hp; }

// SetHp에서는 멤버변수 hp를 this포인터로 매개변수 hp를 참조?한다.

int GetHp() { return hp; }

//GetHp에서는 hp값을 반환한다.

 

호출되서 출력되는 타이밍이 다르면 출력도 따로 만든다.

 

target->SetHp(target->GetHp() - damage);
targer->hp = target->hp - damage;	// 둘 다 같음

// target의 hp에 현재 target의 hp에서 damage를 뺀 값을 대입하겠다.

 

Enum::Type type; 은 Enum 안에 들어있는 Type이라는 구조체?이고 type은 변수?

#include <iostream>
using namespace std;

typedef unsigned int uint

// 구조체 : 정보의 틀, 같은 형태 다른 값

enum Gender
{
	Man,
	Woman
};

struct Student
{
	// 인스턴스 필드 Instance Field : 구조체 내부를 뜻함. 객체가 받는 정보 (객체 = 인스턴스)
	// 인스턴스 내부에 있는 걸 다 멤버라 함
	// (원래는 하나의 변수에 하나의 값밖에 담지 못했는데, 객체는 하나의 변수에 여러 값을 담음)
	// c++부터 구조체 내부에 함수가 올 수 있게 됨(멤버함수=메서드)
	const char* name;	// 배열 자체가 주소이므로 포인터로 사용 가능
	uint age;
	Gender gender;

	// 멤버 함수 / 메서드 Method
	void SetStudentInfo(const char* name,uint age,Gender gender)
	{
		// char str[256];	
		// str = "Hello World";
		
		// 매개변수가 멤버변수보다 우선순위
		// Student::name = name; 로 매개변수, 멤버변수 name 구분하거나
		// this포인터 : 구조체나 클래스 자기 자신을 가리키는 포인터 로 구분함
		this->name = name;	// this는 struct Student를 가르킴, this->name 멤버변수에 name 매개변수 대입
		this->age = age;
		this->gender = gender;
	}

	void PrintStudentInfo()
	{
		cout << "이름은 : " << name << endl;
		cout << "나이는 : " << age << endl;
		cout << "성별은 : " << ((gender == Gender::Man) ? "남자" : "여자") << endl;
	}										// Gender 중 Man
};		

int main()
{
	// const char* str = "Hello World";

	// Student* student = (Student*)malloc(sizeof(Student));
	Student* student = new Student();

	student->SetStudentInfo("김방방", 2, Gender::Man)	// 내 멤버에 있는 걸로 초기화
	student->PrintStudentInfo();

	delete student;
	student = nullptr;
	return 0;
}

 

1. this포인터, 멤버변수, 매개변수

구조체, 클래스 내부를 '인스턴스 필드'라 부르고 그 안에 존재하는 걸 '멤버'라고 부른다. (멤버함수, 멤버변수, 메서드 등)

인스턴스 = 객체, 객체는 하나의 변수에 여러 값을 담는다.

 

this->name = name; 에서 전자 name은 this포인터로 같은 구조체 struct Student에 있는 const char* name의 name을 가르키고(멤버변수), 후자 name은 void SetStudentInfo의 매개변수 name을 가르키는 거 아닐까? 쮓

 

2. 참조

. : 직접참조

-> : 간접참조

 

3. 널포인터

delete student;로 할당되었던 메모리 해제해주고..

student = nullptr; 는 왜 쓰지? 댕글리포인터 때문인가..? 쮓

 

4. 구조체, 클래스

구조체 : 값형식

클래스 : 참조형식

 

5. 선택적 매개변수

선택적 매개변수는 필수적 매개변수 뒤에 오고,

선택적 매개변수는 뒤엔 필수적 매개변수가 올수 없다

필수 다음 선택

ex.

void PrintA(int num, int A = 20)

num이 필수, A가 선택

+ Recent posts