728x90
황기태 저자의 명품 C++ Programming 개정판을 읽고 학습한 내용을 정리한 포스트입니다!
https://search.shopping.naver.com/book/catalog/32436115747
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 |