일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 프로그래머스
- nestJS
- nestjs auth
- 시스템호출
- @Autowired
- 카카오 알고리즘
- OpenCV
- spring boot
- 카카오 코테
- Nodejs
- 카카오
- nestjs typeorm
- python
- thymeleaf
- 코딩테스트
- C언어
- 가상면접사례로배우는대규모시스템설계기초
- Spring
- 컴포넌트스캔
- 해시
- C++
- git
- 스프링
- 알고리즘
- @Component
- 파이썬
- 코테
- TypeORM
- 구조체배열
- AWS
- Today
- Total
공부 기록장 💻
[C++] 클래스와 객체 - 클래스 선언부/구현부, 생성자, 소멸자, 멤버 접근 지정자, 자동 인라인함수, 구조체 본문
[C++] 클래스와 객체 - 클래스 선언부/구현부, 생성자, 소멸자, 멤버 접근 지정자, 자동 인라인함수, 구조체
dream_for 2021. 4. 6. 02:39(명품 C++ 프로그래밍 Ch3)
- 클래스를 설계하다.
- 객체를 생성하고, 객체를 활용한다.
- 클래스를 상속 받거나, C++ 라이브러리에서 제공하는 객체를 사용한다.
객체의 캡슐화(encapsulation)
- 객체의 구성 요소들을 보호
- 일부 요소의 공개 노출: 정보를 교환하고 통신하기 위함
클래스와 객체
- 클래스(class): 객체를 정의하는 틀
- 멤버 변수(상태 - state)
- 멤버 함수(행동 - behavior)
- 객체(object): 클래스라는 틀에서 프로그램실행 도중 실존하는 실체(인스턴스-instance)
클래스 생성
- class 키워드 사용하여 클래스 선언
1. 클래스 선언부(class declaration) : 클래스의 모양 정의
- class 키워드와 클래스 이름으로 선언
- 멤버 변수 선언 - 초기화가능
- 멤버 함수의 원형 선언 - 리턴 타입, 매개 변수 리스트 포함
2. 클래스 구현부(class implementation) : 클래스의 멤버 함수들구현
- 클래스 선언부에 선언된 멤버 함수의 코드를 구현
- 범위지정연산자(::) 사용하여 클래스 이름과멤버 함수를 기술
// 클래스 선언부
class Circle {
public: // 멤버에 대한 접근 지정자 public
int radius; // 멤버 변수
double getArea(); // 멤버함수
};
// 클래스 구현부
double Circle::getArea() {
return 3.14 * radius;radius;
}
객체 생성
- 객체 생성: 클래스 이름 + 객체 이름
- 객체의 멤버 접근: 멤버 연산자 '.'
#include <iostream>
using namespace std;
// 클래스 선언부
class Rectangle {
public: // private 접근 지정자
int width;
int height;
int getArea();
};
// 클래스 구현부
int Rectangle::getArea() {
return width * height;
}
int main() {
Rectangle rect; // Rectangle 클래스의 rect 객체 생성
// 객체의 멤버에 접근
rect.width = 3;
rect.height = 5;
// 멤버 함수 호출
cout << "사각형의 면적은 " << rect.getArea() << "입니다." << endl;
}
생성자(Constructor)
- 객체가 생성될 때 필요한 초기 작업 수행
- 변수의 값을 특정 값으로 설정하는 경우
- 메모리를 동적 할당 받을 때
- 파일을 열 때
- 네트워크를 연결 할 때
- 객체가 생성되는 시접에 오직 한 번만 자동으로 실행
- 생성자 함수의 이름은 클래스 이름과 동일하게 작성되어야 함
- 함수의 원형에 리턴 타입을 선언하지 않음
- 함수 실행 종료를 위해 return 문을 사용할 때에도, 값이 리턴되어서는 안됨 (return; 으로만 작성)
- 생성자는 중복 가능 => 매개변수나 타입이 서로 다르게 선언되어야 함
다음은 Circle 클래스를 사용하여 생성자를 두 개 작성한 예제이다.
main함수에서 donut 객체는 매개변수가 없는 Circle::Circle() 생성자가 호출되며,
구현된 바와 같이 radius가 1로 초기화 된다.
pizza 객체는 30의 값을 인수로 전달하여 Circle::Circle(int r) 생성자가 호출되며,
radius에 30의 r 값이 전달된다.
#include <iostream>
using namespace std;
// 클래스 선언부
class Circle {
public:
int radius;
Circle(); // 기본 생성자
Circle(int r); // 정수형 매개 변수를 전달 받는 생성자
double getArea();
};
// 클래스 구현부(생성자)
Circle::Circle() {
radius = 1; // 반지름 값 초기화
cout << "반지름 " << radius << " 원 생성" << endl;
}
Circle::Circle(int r) {
radius = r; // 반지름 값 초기화
cout << "반지름 " << radius << " 원 생성" << endl;
}
// 클래스 구현부(멤버 함수)
double Circle::getArea() {
return 3.14 * radius * radius;
}
int main()
{
Circle donut; // 매개변수가 없는 생성자 호출
double area = donut.getArea();
cout << "donut 면적은 " << area << endl;
Circle pizza(30); // 매개 변수 있는 생성자 호출 -> 값 39이 r로 전달
area = pizza.getArea();
cout << "pizza 면적은 " << area << endl;
}
donut과 pizza 객체는 각 객체 별로 별도의 객체 크기의 공간을 할당받고, radius 멤버 변수 역시 각 객체의 공간에 별도로 생성된다.
위 예제에서 두 생성자의 구현부에서 radius 값을 초기화하고 출력하는 부분이 중복됨을 확인할 수 있다.
대게 객체를 초기화하는 과정에서 비슷한 코드가 중복되는데, 이를 위해 중복된 초기화 코드를 하나의 생성자로 몰고,
다른 생성자에서 이 생성자를 호출할 수 있도록 하는 것이 '위임 생성자'이다.
위임 생성자(delegating constructor)
- 객체의 초기화를 타겟 생성자에게 위임하는 생성자
- 객체의 생성 과정이 명료하고 단순해진다,
- 타겟 생성자를 호출한뒤, 자신의 코드를 실행하게 된다.
// 위임 생성자
Circle::Circle() : Circle(1){ }
// 타겟 생성자
Circle::Circle(int r) {
radius = r; // 반지름 값 초기화
cout << "반지름 " << radius << " 원 생성" << endl;
}
Circle() 생성자가 호출되면, r에 1를 넘겨주며 Circle(int r) 생성자를 호출하도록 한다.
Circle(int r) 을 타겟 생성자,
그리고 Circle() 생성자는 객체의 초기화를 다른 생성자에 위임한다고 하여 위임 생성자라고 부른다.
클래스가 객체를 생성하기 위해, 생성자가 꼭 존재해야한다.
기본 생성자(default constructor) , 디폴트 생성자
- 클래스에 생성자가단 한개라도선언되지 않은 경우, 컴파일러가 자동으로 생성해주는 생성자
- 매개 변수가 없는 생성자
- 생성자가 없는 클래스는 컴파일러가 자동으로 기본 생성자를 삽입한다.
생성자에서 멤버 변수 초기화 하기
1. 생성자 코드 내부에서 초기화
class Point {
int x, y;
public:
Point();
Point(int a, int b);
};
Point::Point() { x = 0;y = 0; }
Point::Point(int a, int b) { x = a;y = b; }
2. 생성자 서두에 초깃값으로 초기화
class Point {
int x, y;
public:
Point();
Point(int a, int b);
};
Point::Point() : x(0), y(0) {}
// 첫번째 매개변수를 다음과 같이받아 초기화할 수도 있음
// Point::Point(int a) : x(a), y(0) {}
Point::Point(int a, int b) { x = a;y = b; }
3. 위임 생성자 이용
class Point {
int x, y;
public:
Point();
Point(int a, int b);
};
Point::Point() : Point(0,0) {}
Point::Point(int a, int b) { x = a;y = b; }
4. 클래스 선언부에서 직접 초기화
소멸자(destructor)
- 객체 소멸 시 자동으로 호출되는 클래스의 멤버 함수
- 객체가 사라질 때 필요한 마무리 작업
- 동적으로 할당 받은 메모리를 운영체제에게 돌려줄 때
- 열어 놓은 파일을 저장하고 닫는 경우
- 연결된 네트워크를 해제할 때
- 클래스 이름앞에 ~ 를 붙인다.
- 리턴 타입도 없으며, 어떤 값도 리턴해서는안 됨
- 소멸자는 오직 한 개만 존재, 매개변수도 가지지 않음
- 소멸자 선언이 없는 경우, 기본 소멸자(default destructor)가 자동으로 생성
class Circle {
public:
int radius;
Circle();
Circle(int r);
~Circle(); // 소멸자 선언
double getArea();
};
...
// 소멸자 구현
Circle::~Circle(){
cout << "반지름 " << radius << " 원 소멸" << endl;
}
전역/지역 객체는 생성된 순서의 반대 순으로 소멸된다.
지역 객체는 선언되어 있는 해당 함수가 종료될 때, 전역 객체는 프로그램 전체가 종료될 때 소멸된다.
접근 지정
멤버 접근 지정자(access specifier)
- 객체 지향의 캡슐화 구현
- private: 클래스 내의 멤버 함수들에게만 접근 허용(default 접근 지정)
- 클래스의 멤버 변수 - 외부에서 값을 변경하지 못하도록 보호. 생성자의 인수로 전달될 때 값 초기화 가능
- public: 프로그램의 모든 함수의 접근 허용
- 생성자 - 클래스 외부에서 객체를 생성하기 위함 (자식 클래스에서만 생성자를 호출하도록 proteted로 선언하는 경우도 있음)
- protected: 클래스 내의 멤버 함수와이클래스를 상속받는 파생 클래스의 멤버 함수에게만 접근 허용
인라인 함수(inline function)
함수 호출과 실행을 마치고 돌아오는 과정에서 발생하는 함수호출 오버헤드(overhead) 로 인한 실행 속도 저하를 막기 위해 도입된 기능
- inline 키워드 이용
- 인라인함수를 호출하는 곳에 인라인 함수의 코드를 그대로 삽입하여 함수 호출이 일어나지 않게함
- 장점: 함수 호출에 대한 오버헤드가 발생하지 않으므로 프로그램의 실행 속도를 향상시킴
- 단점: 함수 코드를 삽입하므로 호출하는 곳이 여러 군데 있으면 전체 크기가 늘어남
클래스 멤버 함수의 인라인 선언(자동 인라인 함수)
- 생성자를 포함한 클래스의 모든 멤버 함수가 인라인으로 선언될 수 있다.
- 멤버 함수의 크기가 작은 경우, 클래스의 선언부에 직접 구현 가능 (인라인 선언 없어도 됨-컴파일러에 의해 인라인 자동 처리)
- 제약 사항: 재귀 함수(recursion). static 변수, 반복문, switch문, goto 문을 가진 함수는 인라인 함수로 허용하지 않음
위에서 작성했던 Circle 클래스의 생성자, 소멸자, 멤버 함수들을
클래스 구현부에서 인라인 형식으로 작성하였다.
// 클래스 선언부
class Circle {
public:
int radius;
// 멤버 함수를 인라인으로 작성
Circle() :Circle(1) {};
Circle(int r) {
radius = r;
cout << "반지름 " << radius << " 원 생성" << endl;
};
double getArea() {return 3.14*radius*radius};
~Circle() {};
};
C++ 의 구조체
C++ 프로그램의 구조체는 상속, 멤버, 접근 지정 클래스와 그 기능이 모두 같다.
다른 한 가지는, 디폴트 접근 지정이 public이라는 점이다.
다만 구조체의 객체를 생성할 때, struct 키워드를 생략한다.
헤더 파일과 cpp 파일 분리
- header 파일: 클래스 선언부 (중복 방지를 위해 조건 컴파일문 사용 - #ifndef, #define, #endif)
- cpp 파일: 클래스 구현부 (헤더파일 추가)
- main.cpp 파일: main 함수, 전역 변수 (헤더파일 추가)
'# Language & Tools > C++' 카테고리의 다른 글
[C/C++] 문자열 처리 함수 c_str(), atoi(), stoi() (0) | 2021.04.09 |
---|---|
[C++] string 클래스 - string 문자열 객체 동적 생성, string 멤버 함수 사용 (0) | 2021.04.07 |
[C++] 문자열 입력 - <cstring> cin.getline, <string> - getline (0) | 2021.04.06 |
명품 C++ Programming 2장 실습 문제 - C++ 표준 입출력, cin, cout, string 객체, getline 함수 (0) | 2021.03.18 |
[C/C++] C++ 프로그래밍 기본 (0) | 2021.03.17 |