구조체
-클래스는 c와 c++ 언어를 구분짓는 가장 큰 특징이다
-클래스는 구조체의 확장으로 이해할 수 있다.
-구조체는 다양한 형태의 자료집합을 이용해 정의할 수 있다.
#include <iostream>
struct Monster
{
double hp;
double mp;
char level;
};
int main()
{
Monster mob1; //구조체 변수 선언
//구조체의 멤버변수에 접근하기 위해서는 . 연산자를 사용한다
mob1 = { 67.5,34.2,'c' }; //초기화
Monster mob2 = mob1; //복사
mob1.level = 'b';//멤버변수에 접근하여 변경
return 0;
}
클래스
-클래스란 기본적으로 멤버 데이터뿐만 아니라 멤버 함수를 가지는 하나의 구조체이다.
-클래스는 객체지향 프로그래밍의 기법에서 가장 중심 개념이다.
-클래스형의 변수를 객체 또는 인스턴스라고 한다.
객체
-객체는 자신만의 유일한 특성과 상태(state), 행동(behavior)을 갖는다.
-객체의 상태(state)는 데이터 필드 즉 변수로 표현된다.
-객체의 행동(behavior)은 함수에 의해 정의된다.
-객체의 멤버란 데이터필드와 함수를 의미하며, 이를 멤버변수와 멤버함수라 부른다.
-객체가 생성된 후에는 점 연산자(.)를 사용하여 데이터에 접근하고 함수를 호출한다.
-객체의 멤버함수는 같은 클래스의 모든 객체에 공유되므로 단 하나의 복사본만 생성된다. 그러므로 객체의 실제크기는 크지 않다.
-C++에서 하나의 객체로부터 다른 객체로 내용을 복사하기 위해 대입 연산자(=)를 사용할 수 있다. 기본적으로 한 객체의 각각의 데이터 필드는 다른 객체의 대응 부분으로 복사된다.
클래스와 객체의 관계
-클래스는 객체가 어떻게 생겨야 하는지를 적어놓은 설계도
-객체는 그 설계도(클래스)를 통해 만들어진 인스턴스(instance)
-클래스에는 멤버변수를 초기화하기 위한 생성자가 있다.
생성자
-클래스에 일반변수처럼 객체를 생성할 때 초기값을 주는 것
-생성자는 1)클래스 자신과 같은 이름을 가지며, 2)반환유형을 가질 수 없고, 3)생성자는 객체가 생성될 때 자동호출되며, 4)생성자도 오버로딩을 적용할 수 있고, 5)접근 지정자가 public:으로 설정되어야 한다.
-프로그래머가 생성자를 만들지 않을 경우 '기본생성자'(default constructor)를 만들어 놓는데 이는 매개변수도 없고 내용도 없으므로 아무 일도 하지 않는다.
-그런데 프로그래머가 매개변수를 갖는 생성자를 만들어주면 컴파일러는 더 이상 기본 생성자를 제공하지 않는다. 즉, 매개 변수가 있는 생성자를 만들어 사용하던 중 매개변수를 갖지 않는 생성자가 필요하다면 이를 직접 정의하고 사용해야 한다.
#include <iostream>
#include <cstring>
using namespace std;
class Profile // 프로그래머 정의 클래스는 첫문자를 대문자로 하는 것이 좋다
{
public:
//데이터 필드
int age;
char job[100];
//생성자
Profile();
Profile(int age) : age(age)
//생성자에 초기화목록(initializer list)을 사용하여 초기화
{
strcpy_s(job, "대학생!");
}
Profile(double);//생성자의 오버로딩
//멤버함수
void printProfile()
{
cout << "나이는 " << age << "세에 "
<< "직업은 " << job << "입니다" << endl;
}
};
//----생성자----//
Profile::Profile()
{
age = 20;
strcpy_s(job, "대학생");
}
Profile::Profile(double a)
{
age = (int)a;
strcpy_s(job, "대학생?");
}
//-------------//
int main()
{
Profile p1;
Profile p2(23);
Profile p3(22.156);
p1.printProfile();
//출력:나이는 20세에 직업은 대학생입니다
p2.printProfile();
//출력:나이는 23세에 직업은 대학생!입니다
p3.printProfile();
//출력:나이는 22세에 직업은 대학생?입니다
return 0;
}
클래스의 정의와 구현 분리(파일 분리)
-파일 분리시 클래스 정의부분은 .h파일에 구현 부분은 .cpp파일에 저장(헤더파일 포함해야 함, 범위지정 연산자 ::사용하여 클래스 멤버변수와 멤버함수 구현)하고, main()함수는 또 다른 cpp 파일로 분리한다.
다중 포함 방지
-프로그램 내에서 같은 헤더 파일을 여러번 포함(include)시켜 컴파일 오류가 나는 경우가 발생하는데 다중포함을 방지하기 위해서는 #ifdef와 함께 #define 지시자를 사용한다. 이를 inclusion guard라고 하고 이를 헤더파일에 추가해야 다중 포함을 방지할 수 있다.
익명객체
-종종 객체를 생성하고 단지 한 번만 객체를 사용하는 경우가 있다. 이 경우에는 객체에 이름을 줄 필요가 없는데, 이와 같은 객체를 익명 객체(anonymous object)라고 한다.
Profile p1 = Profile();
//인수 없는 생성자를 사용하여 익명 객체 생성
Profile p2 = Profile(21);
//인수 있는 생성자를 사용하여 익명 객체 생성
클래스에서 인라인 함수
-인라인 함수란 함수의 내용이 함수호출 부분에 그대로 옮겨지는 것이다.
-이는 실행의 흐름이 넘어갔다 돌아오거나 인자를 복사하는 과정에서 생기는 시간을 줄여준다.
-함수가 클래스 정의 내부에서 구현되는 경우에는 자동적으로 인라인 함수가 되며, 구현 부분에 만들고 싶다면 앞에 inline이라는 키워드를 적어 헤더파일로 옮겨야 한다.
-인라인 함수는 짧을 때만 사용하는 것이 좋다.
변수의 범위
-전역 변수는 모든 함수의 바깥에 선언되고 모든 함수에서 접근이 가능하다. 전역 변수의 범위는 선언에서 시작하여 프로그램의 끝까지 계속된다.
-지역 변수는 함수 내부에서 정의된다. 지역 변수의 범위는 선언에서 시작하여 변수가 포함된 블록의 끝까지 계속된다.
-클래스 안에 선언되는 멤버변수는 접근지정자가 private일 때와 public일 때 다르게 동작한다.
private일 때:클래스 안의 생성자와 함수에서만 접근가능
public일 때: 외부함수에서도 객체생성 후 . 연산자 통해 접근가능
-만약 지역변수가 멤버변수와 같은 이름을 가진다면, 지역 변수가 우선권을 가진다. 하지만 클래스 안에서 같은 이름의 변수는 선언하지 않는 것이 좋다.
데이터 필드 캡슐화
-데이터 필드를 직접 수정할 수 있을 경우 데이터가 임의로 수정될 수 있고 클래스의 유지보수가 어려워진다. 그러므로 데이터 필드를 private으로 선언하고 get 함수와 set 함수를 사용하여 데이터필드에 접속해야하는데 이를 데이터 필드 캡슐화(data field encapsulation)이라고 한다.
//Profile.h
//헤더 파일에는 클래스의 정의 부분
//다중 포함 방지
#ifndef PROFILE_H
#define PROFILE_H
class Profile
{
public:
Profile();
Profile(int age);
Profile(double);
//함수가 클래스의 정의 내부에서 정의된다면,
//inline을 붙이지 않아도 저절로 inline 함수이다
int getAge() { return age;} //inline 함수를 만드는 첫번째 방법
char* getJob();
void setAge(int newAge);
void printProfile();
private:
int age;
char job[100];
};
inline char* Profile::getJob()
{
return job;
}
#endif
/
//Profile.cpp
//클래스의 구현 부분
#include <iostream>
#include <cstring>
#include "Profile.h" //헤더 파일 포함
using namespace std;
Profile::Profile()
{
age = 20;
strcpy_s(job, "대학생~");
}
Profile::Profile(int age) : age(age)
{
strcpy_s(job, "대학생!");
}
Profile::Profile(double a)
{
age = (int)a;
strcpy_s(job, "대학생?");
}
void Profile:: printProfile()
{
cout << "나이는 " << age << "세에 "
<< "직업은 " << job << "입니다" << endl;
}
void Profile::setAge(int newAge)
{
age = newAge;
if (age > 30)
{
strcpy_s(job, "직장인");
}
}
/
//testProfile.cpp
//main 함수 부분
#include <iostream>
#include "Profile.h" //헤더파일 포함
using namespace std;
int main()
{
Profile p1;
Profile p2(23);
Profile p3(22.156);
p1.printProfile();
//출력:나이는 20세에 직업은 대학생~입니다
p2.printProfile();
//출력:나이는 23세에 직업은 대학생!입니다
p3.printProfile();
//출력:나이는 22세에 직업은 대학생?입니다
Profile p4 = Profile(25); //인수 있는 익명 객체 생성
p4.printProfile();
//출력:나이는 25세에 직업은 대학생!입니다
p4.setAge(30); //private로 선언된 멤버변수를 변경함
p4.printProfile();
//출력:나이는 30세에 직업은 대학생!입니다
return 0;
}
'프로그래밍 공부흔적 > C++' 카테고리의 다른 글
[C++] 상속 (0) | 2021.06.06 |
---|---|
[C++] 연산자 오버로딩 (0) | 2021.06.06 |
[C++] 해시 문제를 풀 때 쓴 vector STL 정리 (0) | 2020.12.30 |
[C++] 배열에 대한 이야기들 정리 (0) | 2020.12.02 |
댓글