728x90
황기태 저자의 명품 C++ Programming 개정판을 읽고 학습한 내용을 정리한 포스트입니다!
https://search.shopping.naver.com/book/catalog/32436115747
# 생성자
- C++에서 객체를 생성할 때는 객체를 초기화할 수 있다.
- 클래스에서는 객체가 생성될 때 자동으로 실행되는 생성자(constructor)라는 특별한 멤버 함수를 이용하여 객체를 초기화한다.
특징
- 생성자의 목적은 객체가 생성될 때 필요한 초기 작업을 위함이다.
- ex) 멤버 변수의 값을 특정 값으로 설정(변수 초기화)하거나, 메모리를 동적으로 할당 받기 등 객체를 사용하기 전 필요한 조치를 하기 위함
- 생성자 함수는 오직 한 번만 실행
- 각 객체가 생성되는 시점에 오직 한 번 자동 실행
- 이름은 클래스 이름과 동일하게 작성되어야 한다.
- 반드시 클래스 이름과 동일하게 작성함으로써 다른 멤버 함수와 쉽게 구분
- 생성자 함수의 원형에 리턴 타입 선언하지 않는다.
- void도 설정하면 안된다.
- 종료를 위해서는 return; 만 사용해야됨
- 생성자는 중복 가능
- 매개 변수 또는 타입이 달라야한다.
위임 생성자(delegating constructor) => 생성자가 다른 생성자 호출
- 보통 한 글래스의 생성자들에는 대게 객체를 초기화하는 비슷한 코드가 중복
- 따라서, 중복된 초기화 코드를 하나의 생성자 코드로 몰고, 다른 생성자에서 호출하도록 만든 것!
#include <iostream>
using namespace std;
class Circle {
public:
int radius;
Circle(); // 기본 생성자
Circle(int r); // 매개 변수 있는 생성자
double getArea();
};
Circle::Circle() : Circle(1) { }// 타겟 생성자
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); // 매개 변수 있는 생성자 호출
area = pizza.getArea();
cout << "pizza 면적은 " << area << endl;
}
- Circle() 생성자가 호출되면 Circle() 생성자는 자신의 코드를 실행하기 전에 Circle(int r) 생성자를 호출하여, r에 1을 넘겨주어 radius를 1로 초기화하고 반지름과 원 생성을 대신 출력
- 객체의 초기화 작업이 코딩된 Circle(int r) => 타겟 생성자
- Circle() 생성자는 객체의 초기화를 다른 생성자에 위임한다고 해서 위임 생성자(delegating constructor)라고 부름
- 타겟 생성자에 객체 초기화를 전담 => 객체의 생성 과정이 명료(clear)해지고 단순(simple) 해진다.
# 생성자와 멤버 변수 초기화
1. 생성자 몸체에서 멤버 변수 초기화
- 따지고 보면 초기화가 아닌 할당이다.
- 기본 변수가 생성된 후, 멤버 변수값이 할당 된다.
class Point {
int x=0; y=0;// 복사 초기화
double value2(2.2); // 직접 초기화
char value3 {'c'}; 유니폼 초기화
...
}
2. 생성자 서두에 초깃값으로 초기화 => 생성자 이니셜라이져( = 멤버 이니셜라이져 = 생성자 멤버 초기화 리스)
- 생성자 이름 뒤에 콜론(:)을 붙여서 표현
class Point {
int x, y;
public:
// 1번째 방법
Point() : x(1), y(1); // 멤버 초기화 리스트를 통해 멤버 변수를 직접 초기화
{
// 멤버 변수를 여기서 할당할 필요가 없다.
}
Point(int a, int b) : x(a), y(b);
void show() { cout << "(" << x << ", " << y << ")" << endl; }
};
- 멤버 이니셜라이져를 사용하면 초기화의 대상이 명확히 인식이 가능
멤버 이니셜라이저를 통해 멤버를 초기화해야만 하는 상황
1. 상수 멤버가 있을 때(const)
- const 변수는 선언과 동시에 초기화를 해야만 오류가 나지 않음
class A {
private:
const int num;
public:
A() : num(0) {}
}
2. 레퍼런스 멤버가 있을 때 (레퍼런스 데이터 멤버)
- const 변수와 마찬가지로 선언과 동시에 초기화를 해야 함
#include <iostream>
class Point
{
int x;
int y;
const int cval; // const 변수
int& r;
public:
Point( int a, int b, int c) : x(a), y(b), cval(c), r(a)
{
// cval = c; // 대입 : 에러 발생한다.
// x = a;
// y = b;
}
};
int main()
{
Point p(1, 2, 10);
}
3. 클래스 안에 디폴트 생성자가 없는 타입이 멤버 데이터로 있을 때 반드시 멤버 초기화 리스트를 사용
- Point의 경우 Point() 생성자가 없기 때문에 Rect(a,b, c, d)가 불렸을 때 p1, p2 멤버 초기화가 바로 되도록 아래 방식의 코딩이 되어야 함
class Point
{
int x;
int y;
public:
Point( int a, int b) : x(a), y(b) {}
};
class Rect
{
Point p1;
Point p2;
public:
Rect(int a, int b, int c, int d) : p1(a,b), p2(c,d) // 무조건 이런 초기화가 좋다.
{
// if, switch와 같은 제어문에 의한 값 셋팅이 필요하다면 이곳에 초기화 해줘야함.
//p1(a, b);
}
};
int main()
{
Rect r (1,2,3,4);
// p1 Point 생성자
// p2 Point 생성자
// Rect 생성자
}
주의사항 : 초기화 순서는 멤버 데이터가 놓인 순서대로 초기화되므로 순서에 주의해야 된다.
기본 생성자(default constructor)
- 클래스에 선언된 어떤 생성자도 없을 때 컴파일러가 자동으로 생성하는 생성자 => 매개변수 없음
- 다만, 생성자가 하나라도 선언된 클래스의 경우, 컴파일러는 기본 생성자를 자동 삽입 xxxx
Rectangle 클래스를 만들며 위의 내용을 복습해보자.
#include <iostream>
using namespace std;
class Rectangle {
public:
int width, height;
Rectangle();
Rectangle(int w, int h);
Rectangle(int length);
bool isSquare();
};
Rectangle::Rectangle() { // Rectangle::Rectangle() : Rectangle(1) {}로 해도 됨
width = height = 1;
}
Rectangle::Rectangle(int w, int h) {
width = w; height = h;
}
Rectangle::Rectangle(int length) { // Rectangle::Rectangle(int length) : Rectangle(length) {}로 해도 됨
width = height = length;
}
bool Rectangle::isSquare() { // 정사각형이면 true를 리턴하는 멤버 함수
if(width == height) return true;
else return false;
}
int main() {
Rectangle rect1;
Rectangle rect2(3, 5);
Rectangle rect3(3);
if(rect1.isSquare()) cout << "rect1은 정사각형이다." << endl;
if(rect2.isSquare()) cout << "rect2는 정사각형이다." << endl;
if(rect3.isSquare()) cout << "rect3는 정사각형이다." << endl;
}
728x90
'Programming Language > C++' 카테고리의 다른 글
[C++] 접근 지정자와 인라인 함수 (0) | 2023.11.29 |
---|---|
[C++] 소멸자 (2) | 2023.11.29 |
[C++] 클래스와 객체 (1) | 2023.11.27 |
[C++] 키보드로 문자열 입력 및 헤더 파일에 관해서 (1) | 2023.11.27 |
[C++] C++ 프로그래밍 기본 (1) | 2023.11.27 |