Language/C++

[C++] CH3 클래스와 객체 (2)

nowkoes 2023. 1. 30. 16:43

소멸자

소멸자 : 객체가 소멸되는 시점에서 자동으로 호출되는 클래스의 멤버 함수.

  • 특징
    1. 소멸자(destructor)의 목적은 객체가 사라질 때 필요한 마무리 작업을 하기 위함이다.
    2. 소멸자의 이름은 클래스 이름 앞에 ~를 붙인다.
    3. 생성자와 같이 리턴 타입이 없고, 어떤 값도 리턴해서도 안 된다.
    4. 생성자와 같이 오직 한 개만 존재하며, 매개 변수를 가지지 않는다.
    5. 소멸자가 선언되어 있지 않으면 기본 소멸자가 자동으로 생성된다.
  • 생성된 반대 순으로 객체가 소멸됨.
    • 반지름 1인 원 생성 -> 반지름 30인 원 생성 -> 반지름 30인 원 소멸 -> 반지름 1인 원 소멸
// 예제 3-7
#include <iostream>
using namespace std;

class Circle
{
public:
	int radius;
	Circle(); // 생성자
	Circle(int r);
	~Circle(); // 소멸자
	double getArea();
};

Circle::Circle() : Circle(1) { }

Circle::Circle(int r)
{
	radius = r;
	cout << "반지름 " << radius << "인 원 생성\n";
}

Circle::~Circle()
{
	cout << "반지름 " << radius << "인 원 소멸\n";
}

double Circle::getArea()
{
	return 3.14 * radius * radius;
}

int main()
{
	Circle circle;
	Circle donut(30);

	return 0;
}

 

지역 객체와 전역 객체

  • 지역 객체: 함수 내에서 선언된 객체로서, 함수가 실행될 때 생성되고 함수가 종료할 때 소멸된다.
  • 전역 객체 : 함수 바깥에 선언된 객체로서, 프로그램이 로딩될 때 생성되고 main이 종료한 뒤 프로그램 메모리가 사라질 때 소멸된다.
// 예제 3-8
#include <iostream>
using namespace std;

class Circle
{
public:
    int radius;
    Circle();
    Circle(int r);
    ~Circle();
    double getArea();
};

Circle::Circle() : Circle(1) {}

Circle::Circle(int r)
{
    radius = r;
    cout << "반지름 " << radius << "인 원 생성\n";
}

Circle::~Circle()
{
    cout << "반지름 " << radius << "인 원 소멸\n";
}

Circle globalDonut(1000); // 전역 객체1
Circle globalPizza(2000); // 전역 객체2

void f()
{
    Circle localDonut(100); // 지역 객체1
    Circle localPizza(200); // 지역 객체2
}

int main()
{
    Circle donut; // 지역 객체3
    Circle pizza(30); // 지역 객체4
    f();
}

 

요약

소멸자
1. 정의: 객체가 소멸되는 시점에서 자동으로 호출되는 클래스의 멤버 함수
2. 특징
 a. 객체가 사라질 때 필요한 마무리 작업 (ex) 메모리 할당 해제) 를 수행
 b. 클래스 이름 앞에 ~ 를 붙여서 작성하고, 매개변수가 없으며, 리턴값도 없음
 c. 클래스 내에 오직 하나만 존재하며, 따로 작성하지 않으면 기본 소멸자가 자동으로 생성됨

지역 객체: 함수 내에 선언되어 함수가 실행될 때 생성되고 함수가 종료할 때 소멸
전역 객체: 함수 바깥에 선언되어 프로그램이 로딩될 때 생성되고 main이 종료한 뒤 소멸

접근 지정

접근 지정자: 객체 지향 언어에서 객체를 캡슐화하고, 외부에서 접근 가능한 공개 멤버와 접근을 막는 비공개 멤버를 구분할 때 사용하는 지정자.

  • 종류: private(비공개), public(공개), protected(보호)
  • 접근 지정은 여러 번 사용될 수 있고, 접근 지정자가 선언되면 다른 접근 지정자가 선언될 때까지 모든 멤버에 대해 적용된다.
  • 기본 접근 지정은 private이다.
    • 클래스의 멤버들은 외부에서 마음대로 접근할 수 있도록 허용해서는 안 되므로, 변수 멤버는 private으로 지정하는 것이 바람직하다.
  • 생성자는 public으로 지정하는 것이 바람직하다.
    • 하지만 의도적으로 외부에서 객체를 생성할 수 없도록 생성자를 private으로 선언하기도 하고, 상속된 클래스에서만 호출하도록 protected로 선언하기도 한다.
// 예제 3-9
#include <iostream>
using namespace std;

class PrivateAccessError
{
private:
    int a;
    void f();
    PrivateAccessError();
public:
    int b;
    PrivateAccessError(int x);
    void g();
};

PrivateAccessError::PrivateAccessError() : a(1), b(1) { }

PrivateAccessError::PrivateAccessError(int x)
{
    a = x; b = x;
}

void PrivateAccessError::f()
{
    a = 5; b = 5;
}

void PrivateAccessError::g()
{
    a = 6; b = 7;
}

int main()
{
    PrivateAccessError objA; 
    // error : 매개 변수 없는 생성자는 private
    PrivateAccessError objB(100);

    objB.a = 10;
    // error : a는 private으로 선언됨
    objB.b = 20;

    objB.f();
    // error: vod f는 private으로 선언됨
    objB.g();

    return 0;
}


요약

접근 지정자
1. 정의: 외부에서 접근 가능한 공개 멤버와 접근을 막는 비공개 멤버를 구분할 때 사용하는 지정자
2. 종류
 - private, public, protected
3. 특징
 - 기본 접근 지정은 private

인라인 함수

오버헤드(overhead): 프로그램의 실행 흐름 중, 추가적으로 자원이 소모되는 현상

인라인 함수(inline function): 짧은 코드로 구성된 함수에 대해, 함수 호출 오버헤드로 인한 프로그램의 실행 속도 저하를 막기 위해 도입된 기능.

  • 함수 앞에 inline 키워드를 이용해 선언한다
inline <자료형> <함수이름>(매개변수)
{
    statement(s);
}
  • 장점: 함수 호출 오버헤드가 없어져 실행 속도가 빨라진다.
  • 단점: 호출하는 곳이 여러 곳 있으면, 전체 크기가 늘어난다 (따라서 작은 함수를 인라인으로 선언해야 좋음)
  • 특징
    • inline 선언은 컴파일러에게 요청하는 것이기 때문에 불필요한 경우 무시될 수 있다.
    • C++에서 멤버 함수의 크기가 작은 경우, 클래스의 선언부에 직접 구현해도 무방하다. (컴파일러가 인라인 함수로 자동 처리함)

함수로 호출하는 것과 인라인으로 처리하는 것의 예제

  • 다음과 같은 함수가 inline 키워드를 붙이기 전에는 for문에 의해 odd(i)함수가 10000번 호출돼서 실행 시간이 길었지만, inline을 이용한 후에는 odd(i) 자리에 i % 2만 존재하게 하므로 속도가 향상됨

 

요약

인라인 함수
1. 정의: 추가적으로 자원이 소모되는 오버헤드 현상을 방지하기 위해 도입된 기능 
2. 장점: 실행 속도가 빨라진다.
3. 단점: 호출하는 곳이 여러 곳 있으면 전체 크기가 늘어난다.
4. 특징
 - 컴파일러에게 요청하는 것이기 때문에 불필요한 경우 무시된다.

C++ 구조체

구조체: 표준 C 구조체에 기능을 확장하여 클래스와 동일한 구조와 기능을 가짐.

  • struct 키워드를 이용해 선언한다.
  • 멤버 변수와 멤버 함수를 가지고, 접근 지정도 해야한다
struct <구조체이름> { statement(s); }
  • 클래스와 구조체의 차이점은 기본 접근 지정자 차이다. 구조체는 public인 반면, 클래스는 private이다.
    • 구조체와 클래스 중 어떤 것을 사용해도 상관없다.
// 예제 3-10
#include <iostream>
using namespace std;

struct StructCircle
{
private:
    int radius;

public:
    StructCircle(int r) { radius = r; }
    double getArea();
};

double StructCircle::getArea()
{
    return 3.14 * radius * radius;
}

int main()
{
    StructCircle waffle(3);
    cout << "면적은 " << waffle.getArea() << "입니다.\n";
}

 

요약

구조체
1. 정의: C++언어의 기본 타입을 가지고 새롭게 정의할 수 있는 사용자 정의 타입
2. 특징
 - 클래스와 차이점은 구조체의 기본 접근 지정자가 public이라는 것.

바람직한 C++ 프로그램 작성법

  • 클래스마다 선언부는 헤더 파일에, 구현부는 cpp 파일에 분리하여 작성한다.
  • main() 등 함수나 전역 변수는 한 개 이상의 cpp 파일에 나누어 작성한다.
  • 이때 분리한 헤더 파일은 전처리문으로 include 해야 한다.
  • 헤더 파일의 중복이 발생할 수 있는데, 이를 방지하기 위해 조건 컴파일 문을 삽입하면 된다.
#ifndef <헤더파일 이름>
#define <헤더파일 이름>
...
    
#endif

문제풀이: [GitHub - maloveforme/Cpp]

반응형