프로그램이 시작할 때 생성되고, 클래스 당 하나만 생성된다. 그래서 클래스 멤버라고 불린다.
중요한 것은, 클래스의 모든 객체들이 공유하여 사용하는 멤버이다.
class-name::staticMemName으로 접근해야 한다.object-name->function, object-name.functionclass-name::functionclass student {
public:
int stdNum;
static int stdCount; // 전역 멤버 변수
static void PrintStdCount(); // 전역 멤버 함수
}
// static 변수 공간 할당 (프로그램 전역 공간에 생성해야함)
int student::stdCount =1 ;
// 전역 함수 안에서는 일반 멤버에 접근할 수 없음 (어떤 객체의 멤버인지 몰라서)
void student::PrintStdCount() {
// do something...
}
프로그램 시작 시, 멤버가 생성되며 객체가 생기기 전에도 이미 존재하는 멤버이다.
static멤버가 사용된 클래스의 객체가 사라져도 여전히 존재한다.
프로그램과 생성을 같이하기 때문에, 프로그램이 종료될 때 함께 소멸한다.
객체가 생성될 때 함께 생성되고, 객체마다 객체 내에 생성된다.
그래서 인스턴스 멤버라고 불린다.
void student::PrintStdCount() {
student st1("",0);
std.stdNum = 202105020;
}
멤버 변수의 값을 변경할 수 없으므로, const 객체 선언 후에는 대입을 진행할 수 없다.
그리고 멤버 변수의 값을 변경하는 멤버 함수를 호출할 수 없다.
=> 즉, const멤버 함수만 호출할 수 있다.
Stack s1(4);
const Stack st2; // 디폴트 생성자로 초기화 진행
s2 = s1; // (X)
실질적으로 멤버 변수를 변경하지 않는 일반 멤버 함수일지라도, 값을 변경하지 않는다는 것을 증명하는
const를 부여받아야만 const객체가 호출할 수 있다.
객체의 값을 변경하지 않기로 약속하는 멤버 함수이고, 이는 "이 함수에서 멤버 변수의 값을 변경하지 않으므로, const 객체가 이 멤버함수를 호출해도 안전하다."는 의미이다.
지정방법은 함수의 선언 & 정의 모두 const 키워드를 지정한다.
// 선언부
class ClassName {
멤버함수 선언 const;
}
// 구현부
returnType className::function() const {
// 멤버 변수 값 변경 X
// 일반 멤버 함수 호출 X
}
해당 함수 안에서는 멤버 변수의 값을 변경 & 다른 일반 멤버 함수 호출이 불가능하다.
우리가 배운 배열과 똑같은 방식으로 선언한다. ( 2차원 배열또한 same )
객체 배열 생성할 때 원소의 값을 따로 지정하지 않으면 항상 디폴트 생성자로 초기화된다.
// 디폴트 생성자로 초기화
student stdArr[3];
// 배열의 원소는 `생성자`를 나열하여 지정
student stdArr2[] = {student(10,"std1"), student(20,"std2"),student(30,"std3")}
만약, 클래스 내에 직접 생성자를 만들었는데 디폴트 생성자가 없다면 error 발생!
class student{
private:
int stdNum;
public:
student(int stdNum);
//student();
}
int stdArr3[]; // 디폴트 생성자가 존재하지 않아서 error 발생
if, 동적 메모리로 배열을 할당 & 해제하고 싶다면
// 동적 객체 배열은 항상 디폴트 생성자로 초기화
// 고로, 해당 클래스에 `디폴트 생성자가 없다면` 동적 객체 배열 생성 불가능
className *pointerName = new className[array_size];
delete[] pointerName;
if. 포인터 배열로 사용하고 싶다면
// 배열의 원소 : student객체의 주소 ( student의 pointer )
student* stdArr[2] = { new student(10,"std1"), new student(20,"std2") };
for(int i = 0; i < 2; i++) {
delete stdArr[i];
}
우리가 배운 포인터와 동일한 방식으로 선언되고 사용된다.
객체 포인터로 멤버에 접근할 때는 객체 포인터->멤버 를 작성한다.
student std1;
std1.stdNum =202105020;
student *std_pointer = &std1;
if, 동적 메모리로 할당 & 해제하고 싶다면
className.pointerName = new className; // 디폴트 생성자 사용
className.pointerName = new className(매개 변수); // 매개변수가 있는 생성자 사용
delete pointerName;