728x90

황기태 저자의 명품 C++ Programming 개정판을 읽고 학습한 내용을 정리한 포스트입니다!

https://search.shopping.naver.com/book/catalog/32436115747

 

C++ Programming : 네이버 도서

네이버 도서 상세정보를 제공합니다.

search.shopping.naver.com

 

static

  • static은 변수와 함수의 생명 주기(life cycle)와 사용 범위(scope)를 지정하는 방식(storage class) 중 하나
  • 생명 주기
    • 프로그램이 시작할 때 생성되고 프로그램이 종료할 때 소멸
  • 사용 범위
    • 변수나 함수가 선언된 범위 내에서 사용.
    • 전역(global) 혹은 지역(local)로 구분
  • C++에서 클래스 멤버 변수와 멤버 함수를 포함하여 모든 변수와 함수는 static 지정자로 선언 가능
특성
  • non-static 멤버는 객체가 생성될 때 생성되고 각 객체마다 별도로 생성
    • 즉, 객체와 생명 주기를 같이한다. (ex - 사람이라는 객체에 눈이라는 멤버 변수가 있을 때, 사람이 죽으면 눈도 사라진다)
    • 인스턴스(instance) 멤버
  • static 멤버는 객체의 멤버이지만, 객체가 생기기 전에 이미 생성되어 있고 객체가 사라져도 소멸되지 않는다.
    • 또한, 모든 객체들의 공통된 멤버로서 객체 사이에 공유
    • 클래스(class) 멤버
선언
  • 멤버 함수나 멤버 변수의 선언문 앞에 static 지정자를 붙이면 된다.
  • static 멤버들은 private, public, protected 등 어떤 접근 지정도 가능
class Person {
public:
	int money; // 개인 소유의 돈
	void addModey(int money) {
		this->money += money;
	} // non-static 멤버 선언

	static int sharedMoney; // 공금 // static 멤버
	static void addShared(int n) { // static 멤버
		sharedMoney += n; 
	}
};

int Person::sharedMoney = 10; // static 변수 공간 할당. 반드시 프로그램의 전역공간에 선언

 

money는 인스턴스 멤버로서 각 Person 객체마다 생성되지만, sharedMoney는 Person 객체의 개수와 상관없이 단 한 개만 생성되고, 모든 Person 객체가 sharedMoney와 addShared()를 자신의 멤버로 인식하면서 공유한다.

 

중요한 점!!! 

  • static 멤버 변수는 외부에 전역(global) 변수로 선언되어야 한다.
  • static 멤버 변수는 변수의 공간을 할당받는 선언문이 추가적으로 필요한데, 클래스 바깥의 전역 공간에 선언되어야 한다.


static 멤버 사용

1. 객체의 멤버로 접근하는 방법

  • 객체 이름이나 객체 포인터를 이용하여 보통 멤버와 동일하게 다루면 된다.
객체.static멤버
객체포인터->static멤버

 

2. 클래스명과 범위지정 연산자(::)로 접근

  • 클래스 당 하나만 존재하기에 클래스의 이름으로도 접근할 수 있다.
클래스명::static멤버
han.sharedMoney = 200;
// 아래와 동일
Person::sharedMoney = 200;
  • but!! non-static 멤버는 클래스명으로 접근할 수 없다.
  • 객체의 이름이나 포인터로만 접근 가능하다.
Person::money = 100; // 컴파일 오류. non-static 멤버는 클래스명으로 접근 불가
Person::addMoeny(200); // 컴파일 오류. non-static 멤버는 클래스명으로 접근 불가

// 아래와 같이 접근
lee.money = 100;
Person *p = &lee;
p->addMoney(200);

 


static 활용

전역 변수나 전역 함수를 클래스에 캡슐화
  • OOP 언어에서 추구하는  핵심 가치가 캡슐화
  • 전역 함수나 전역 변수를 없애고 모든 함수나 변수를 클래스 안에 선언하도록 한다.
  • JAVA는 100% 캡슐화하지만, C++은 C와의 호환성 때문에 100% 캡슐화하지 못한다.
  • 따라서, 전역 변수와 전역 함수를 선언하지 말고, static 멤버로 선언하여 캡슐화하는 것을 습관화하자..!
#include <iostream>
using namespace std;

class Math {
public:
	static int abs(int a) { return a>0?a:-a; }
	static int max(int a, int b) { return (a>b)?a:b; }
	static int min(int a, int b) { return (a>b)?b:a; }
};

int main() {
	cout << Math::abs(-5) << endl;
	cout << Math::max(10, 8) << endl;
	cout << Math::min(-3, -8) << endl;
}

 

객체 사이에 공유 변수를 만들고자 할 때
  • 생성된 원의 개수를 기억하는 numOfCircles 멤버 변수를 Circle 클래스에 static으로 선언하여 모든 Circle 객체들이 공유한다.
  • 그리고 이 멤버 변수를 리턴하는 함수 getOfCircles()를 static 타입으로 작성한다.
#include <iostream>
using namespace std;

class Circle {
private:
	static int numOfCircles;
	int radius;
public:
	Circle(int r=1); 
	~Circle() { numOfCircles--; } // 생성된 원의 개수 감소
	double getArea()  { return 3.14*radius*radius;}
	static int getNumOfCircles() { return numOfCircles; }
}; 

Circle::Circle(int r) {
	radius = r;
	numOfCircles++; // 생성된 원의 개수 증가
}

int Circle::numOfCircles = 0; // 0으로 초기화

int main() {
	Circle *p = new Circle[10]; // 10개의 생성자 실행, numOfCircles =10
	cout << "생존하고 있는 원의 개수 = " << Circle::getNumOfCircles() << endl;

	delete [] p; // 10개의 소멸자 실행, numOfCircles = 0
	cout << "생존하고 있는 원의 개수 = " << Circle::getNumOfCircles() << endl;

	Circle a; // 생성자 실행, numOfCircles = 1
	cout << "생존하고 있는 원의 개수 = " << Circle::getNumOfCircles() << endl;

	Circle b; // 생성자 실행, numOfCircles = 2
	cout << "생존하고 있는 원의 개수 = " << Circle::getNumOfCircles() << endl;
}

 


static 멤버 함수의 특징

static 멤버 함수는 오직 static 멤버들만 접근
  • static 멤버 함수는 오직 static 멤버 변수에 접근하거나 static 멤버 함수만 호출 가능
  • 객체가 생성되지 않은 어떤 시점에서도 호출 가능하며, 클래스 이름으로 직접 호출될 수 있기에, static 멤버 함수에서 non-static 멤버에 접근하는 것은 허용되지 않는다.
class PersonError {
	int money;
public:
	static int getMoney() { return money; } // 컴파일 오류.

	void setMoney(int money) {
		this->money = money; // 정상 코드
	}
};

int main() {
	int n = PersonError::getMoney();

	PersonError errorKim;
	errorKim.setMoney(100);
}
  • 위 코드에서 static 멤버 함수 getMoney()가 non-static 멤버 money에 접근 하도록 작성되어 컴파일 오류가 발생
  • main()이 시작하기 전에, static 멤버 함수가 먼저 읽히기 때문이다.
  • 반대의 경우, non-static이 static에 접근하는 것은 허용된다.

 

static 멤버 함수는 this를 사용할 수 없다.
  • static 멤버 함수는 객체가 생기기 전부터 호출 가능
  • static 멤버 함수에서 this를 사용할 수 없도록 제약한다.
class Person {
public:
	double money;
	static int sharedMoney;
    ...
	static void addShared(int n) {
		this->sharedMoney + n;
	}
};
  • this를 사용하므로 컴파일 오류가 발생한다.
728x90

'Programming Language > C++' 카테고리의 다른 글

[C++] 연산자 중복  (0) 2023.12.06
[C++] 프렌드  (1) 2023.12.05
[C++] 함수 중복  (0) 2023.12.04
[C++] 복사 생성자  (1) 2023.12.04
[C++] 참조에 의한 호출, call by reference  (0) 2023.12.04