본문 바로가기
c++

25. [C++] 클래스에서의 static키워드

by yoonjunho 2023. 1. 21.

클래스에서 사용되는 static키워드

(static이 class에서 사용되는 방법은 3가지가 있다.)

1. static member function

2. static member variable

3. static variable in fuction (fuction에서 사용되는 static variable)-(2. 번과 관련된 방법)

 

 

1. static member fuction

 

그냥 member 변수와 member함수는 객체를 생성 해야지만 변수를 참조하고 함수를 호출할 수 있다.

statick member변수와 함수는 객체를 생성안해도 호출이 된다. 그리고 둘 다 객체로 부터 호출할 수도 있다. 

 

 

 

-static member 함수를 객체를 생성해서 호출

#include <iostream>
class Cat {
public:
	const static int a = 24;
	void speak() {//그냥 member function
		std::cout << "meow" << std::endl;
	};
	static void staticSpeack() {
		std::cout << "CAT!" << std::endl;
	}
private:
	int mAge;
};

int main() {
	Cat kitty;

	kitty.staticSpeack();

	return 0;
}

-static member 함수를 객체 없이 호출

#include <iostream>
class Cat {
public:
	const static int a = 24;
	void speak() {//그냥 member function
		std::cout << "meow" << std::endl;
	};
	static void staticSpeack() {
		std::cout << "CAT!" << std::endl;
	}
private:
	int mAge;
};

int main() {
	
	Cat::staticSpeack();

	return 0;
}

 

 

static member function은 object와 연관x ->그냥 호출 가능

this는 object의 address를 가리키는데, 

static member function은 그러한 this(object address)와 binding이 되어있지 않기 때문에, 

object를 생성하지 않아도 call이 될 수 있다. 

그래서 member variable에 접근할 수 없다. (this로 가리킬 수 없다.)

member function도 호출할 수 없다. (member function도 this라는 주소를 통해서 호출하기 때문이다.)

 

그런데 static member function은 member function이므로, 객체를 선언하고나면 그 객체에서 statick member function은 call을 할 수 있다.

 

그냥 member 변수와 member함수는 객체를 생성 해야지만 거기서 쓰고 호출할 수 있다.

statick member함수는 객체를 생성안해도 호출이 된다.

ex) 

-객체를 생성하지 않았기 때문에, static member 함수는 호출 되지만, 그 안에 있는 그냥 member함수는 호출이 불가능 하다

class Cat {
public:
	void speak() {//그냥 member function
		std::cout << "meow" << std::endl;
	};
	static void staticSpeack() {
		std::cout << "CAT!" << std::endl;
		speak();//static member 함수에서 그냥 memeber함수 호출 불가능
	}
private:
	int mAge;
};

int main() {
	
	Cat::staticSpeack();

	return 0;
}

ㄴ 이건 안된다.

 

-static member함수는 그냥 호출하면서, 인자로  따로 생성한 객체를 넘겨주어 그 객체를 통해 그냥 member함수를 호출했다. 

#include <iostream>
class Cat {
public:
	void speak() {//그냥 member function
		std::cout << "meow" << std::endl;
	};
	static void staticSpeack(Cat &cat) {
		std::cout << "CAT!" << std::endl;
		cat.speak();//이렇게 객체를 생성해서 그 객체에 대해서 호출하면 된다.
	}
private:
	int mAge;
};

int main() {
	Cat kitty;//object(객체)
	kitty.speak();
	Cat::staticSpeack(kitty);

	return 0;
}

ㄴ이건 된다.

 

-static member함수는 그냥 호출하고, 인자로 생성한 객체의 참조자를 넘겨주어, 그냥 멤버 변수를 참조했다.

객체를 생성하고 참조자로 이어주면 이것도 된다.

#include <iostream>
class Cat {
public:
	void speak() {//그냥 member function
		std::cout << "meow" << std::endl;
	};
	static void staticSpeack(Cat &cat) {
		std::cout << "CAT!" << std::endl;
		std::cout << cat.mAge;
	}
private:
	int mAge;
};

int main() {
	Cat kitty;//object(객체)
	kitty.speak();
	Cat::staticSpeack(kitty);

	return 0;
}

 

근데 위 처럼 객체 생성 안하고 그냥하면 call안된다.

 

#include <iostream>
class Cat {
public:
	void speak() {//그냥 member function
		std::cout << "meow" << std::endl;
	};
	static void staticSpeack() {
		std::cout << "CAT!" << std::endl;
	}
private:
	int mAge;
};

int main() {
	Cat kitty;//object(객체)
	kitty.speak();
	kitty.staticSpeack();

	return 0;
}

ㄴ이렇게 객체를 가지고 static member 함수 호출하는 것은 된다.

 

 

 

공부한 강의 :

https://www.youtube.com/watch?v=oD6fKjyX5to 

 

 

2. 정적(static) 멤버 변수

-클래스를 만들고 그 클래스의 객체들을 여러 개 만들면,

멤버 변수는 객체마다 별도로 다 새로 생긴다. 

멤버 함수는 새로 생기지 않고 하나를 만들어서 모두 같이 공유한다. 

-이때 static 멤버 변수는 마치 함수처럼 하나만 만들어서 그 클래스의 모든 객체들이 공유한다.

-static멤버 변수는 클래스 안에서 선언하고, 클래스 밖에서 전역으로 정의한다.(즉, main함수 밖에서 초기화 한다.)

- static멤버 변술르 정의할 때, 값을 안적으면 자동으로 0으로 초기화된다.

 

그냥 member 변수와 member함수는 객체를 생성 해야지만 변수를 참조하고 함수를 호출할 수 있다.

statick member변수와 함수는 객체를 생성안해도 호출이 된다. 그리고 둘 다 객체로 부터 호출할 수도 있다. 

 

-static member 변수를 객체를 생성해서 호출 (그래도 static member 변수는 클래스당 1개씩이다.)

#include <iostream>
class Cat {
public:
	const static int a = 24;
	void speak() {//그냥 member function
		std::cout << "meow" << std::endl;
	};
	static void staticSpeack() {
		std::cout << "CAT!" << std::endl;
	}
private:
	int mAge;
};

int main() {
	Cat kitty;

	std::cout << kitty.a;

	return 0;
}

-static member 변수를 객체 없이 호출

#include <iostream>
class Cat {
public:
	const static int a = 24;
	void speak() {//그냥 member function
		std::cout << "meow" << std::endl;
	};
	static void staticSpeack() {
		std::cout << "CAT!" << std::endl;
	}
private:
	int mAge;
};

int main() {

	std::cout << Cat::a;


	return 0;
}

 

-static 변수를 선언하는 위치에 따라 성질이 달라진다.

-(1)public에 선언하는 경우

-(2)private에 선언하는 경우

-(3) 3. static member variable in a function인 경우 가 있다. <-이게 아까 static키워드를 클래스에서 사용하는 경우 3번이다.

멤버 함수 안에서 static 변수를 선언하면, 접근이 불가능한 더 안전한 코드가 된다. 

 

(1) . public에 선언한 경우

ㄴ외부에서 클래스 이름만 가지고 접근이 가능하다.

#include <iostream>
class Cat {
public:
	void speak() {//그냥 member function
		count++;
		std::cout <<count<< "meow" << std::endl;
	};
	static int count;//public에 선언됨, 그냥 member function에서 호출되는 중
	
	static void staticSpeack() {
		std::cout << "CAT!" << std::endl;
	}
private:
	int mAge;
};
int Cat::count = 0;//여기서 접근 가능, 0으로 초기화 해주었다.

int main() {
	Cat kitty, nabi;
	kitty.speak();
	Cat::count = -999;
	nabi.speak();
	return 0;
}

-(2)private에 선언하는 경우

ㄴmain밖에서는 클래스 이름만 가지고 접근 가능,

main안에서는 클래스 이름만 가지고 접근 불가능

 

*멤버 함수에서만 접근이 가능하다.* <-핵심(따라서 멤버 함수 안에서 선언해도 된다.)

#include <iostream>
class Cat {
public:
	void speak() {//그냥 member function
		count++;
		std::cout <<count<< "meow" << std::endl;
	};
	
	static void staticSpeack() {
		std::cout << "CAT!" << std::endl;
	}
private:
	static int count;//public에 선언됨, 그냥 member function에서 호출되는 중

	int mAge;
};
int Cat::count = 11; //<-여기에선 클래스 이름만 가지고 접근 가능
int main() {
	Cat kitty, nabi;
	kitty.speak();//멤버함수는 접근 가능
	//Cat::count = -999;//<-컴파일 에러(클래스 이름만 가지고 접근 불가능)
	nabi.speak();//멤버함수는 접근 가능
	return 0;
}

 

 

 

-(3) 3. static member variable in a function인 경우

ㄴ외부에서 클래스 이름만 가지고는 접근이 불가능하다. 객체가 있어야 한다.

#include <iostream>
class Cat {
public:
	void speak() {//그냥 member function
		static int count;//public에 선언됨, 그냥 member function에서 호출되는 중
		count++;
		std::cout <<count<< "meow" << std::endl;
	};
	
	static void staticSpeack() {
		std::cout << "CAT!" << std::endl;
	}
private:
	int mAge;
};
//int Cat::count = 0; //여기서 접근 불가능
int main() {
	Cat kitty, nabi;
	kitty.speak();
	//Cat::count = -999;//<-컴파일 에러(클래스 이름만 가지고 접근 불가능)
	nabi.speak();
	return 0;
}

 

static member variale의 기본 개념

 

-멤버변수는 객체마다 생기고,

static memeber variable은 같은 클래스의 모든 객체들이 공통적으로 공유한다.

// 정적 멤버 변수

class Point {
	int x;//접근 지정자를 생략하고 그냥 선언하면 기본적으로 private이다.
	int y;
	static int count; //<-이게 정적 멤버 변수
public :
	Point(int i, int j) { x = i; y = j; }
	int getX() { return x; }
	int getY() { return y; }
};

//클래스의 멤버 변수 선언문에 static이라는 키워드를 붙임
//c언어의 static변수와 의미가 다름
//객체들이 정보를 공유할 목적으로 사용하는 변수
class Dog {
private:
	int age;
public :
	int getAge() { return age; }
	void setAge(int a) {age = a;}

};
int main() {
	Dog happy, merry;//객체의 주소는 this에
	//...
	//...
	//이게 객체를 만든다고 저 클래스 내부 전체가 새로 생기는게 아니다
	//그러면 객체가 100개 1000개가 되었을 때 너무 많다.
	//'변수'만 객체를 새로만들 때 객체마다 새로 생긴다.
	//'함수'는 하나만 만들어 져서 같은 걸 공유한다.
}

여기서 static멤버 변수를 만들면

class Dog {
private:
	static int age;
public :
	int getAge() { return age; }
	void setAge(int a) {age = a;}

};
int Dog::age = 0; //<-이걸 안하면 에러가 난다. 객체가 생성될 때 static멤버 변수가 만들어 지는 게 아니라서 그렇다.
int main() {
	Dog happy, merry;
	//...
	//...
}

이렇게 모든 객체들이 함수만이 아니라 멤버 변수 age도 하나만 만들어서 같은 걸 공유하게 된다.

 

실습 예제 :

#include <iostream>

using std::cout;

class Point {
	int x;
	int y;
	static int count;//선언
public:
	Point() { cout << ++count<<"\n"; }
	~Point() { cout << --count<<"\n"; }
};
int Point::count = 0;//정의
int main() {
	Point p1, p2, p3;
	return 0;
}

생성될 때, 생성자의 정의에 따라 공유하는 count변수를 1씩 증가시킨다.

프로그램이 종료될 때, 소멸자의 정의에 따라 공유하는 count변수를 1씩 감소시킨다.

( count의선언은 클래스 안에서, 정의(초기화)는 전역공간에서 0으로 초기화 했다. )

 

#include <iostream>

using std::cout;

class Point {
	int x;
	int y;
	static int count;//선언
public:
	Point() { cout << ++count<<"\n"; }
	~Point() { cout << --count<<"\n"; }
};
int Point::count;//정의
int main() {
	Point p1, p2, p3;
	return 0;
}

ㄴ이렇게 static멤버 변수의 초깃값을 안주면 자동으로 0으로 초기화 된다.

https://www.youtube.com/watch?v=oD6fKjyX5to&nbsp; &nbsp; &nbsp;4분 48초

이렇게 object는 stack영역에 위에서 아래로 쌓여서 kitty와 nabi는 int하나 있으니 4바이트씩 가진다.

근데, static member variable은 static영역이라고 따로 있는 곳에 할당이 되서 object들이 같은 메모리 공간을 공유하게 된다.

 

 

공부한 강의 : https://www.youtube.com/watch?v=3CH_UmYzSJo 

 

 

 

 

 

정적(static) 멤버 함수

 

예제 : 

 

'c++' 카테고리의 다른 글

27. [C++] 함수 오버로딩, 디폴트 인자  (0) 2023.01.24
26. [C++] explicit  (0) 2023.01.24
24. [C++] static과 const 멤버  (0) 2023.01.21
23. [C++] friend 클래스 , friend 멤버 함수  (0) 2023.01.21
22. [C++] friend  (0) 2023.01.20