Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 인공지능
- hackerschool
- php
- Shellcode
- 딥러닝
- webhacking
- 러닝 스칼라
- Python
- Javascript
- 챗GPT
- ChatGPT
- c
- BOF 원정대
- Web
- c++
- 리눅스
- 백엔드
- hackthissite
- deep learning
- 러닝스칼라
- Linux
- Scala
- mysql
- 경제
- 파이썬
- BOF
- backend
- flask
- hacking
- 웹해킹
Archives
- Today
- Total
jam 블로그
[C++] 006. static 멤버와 const 멤버 본문
728x90
I. 클래스와 const
const 키워드에 대한 복습
- 첫째. const 키워드는 변수의 선언 앞에 붙어서 변수를 상수화한다.
- 둘째. const 키워드는 포인터가 가리키는 데이터를 상수화 한다.
- 셋째. const 키워드는 포인터 선언 시 이름 앞에 붙어서 포인터 자체를 상수화한다.
- 멤버 변수의 상수화, 그리고 초기화
- #include <iostream>
- using namespace std;
- class Student
{
const int id;
int age;
char name[20];
char major[30];
public:
Student(int _id, int _age, char* _name, char* _major)
{
id = _id;
age = _age;
strcpy(name,_name);
strcpy(major,_major);
} - void ShowData()
{
cout<<"이름 : "<<name <<endl;
cout<<"나이 : "<<age<<endl;
cout<<"학번 : "<<id<<endl;
cout<<"학과 : "<<major<<endl;
}
}; - int main()
{
Student Kim(1234,23,"l","3");
Student Ho(12315,34,"g","re"); - Kim.ShowData();
cout<<endl;
Ho.ShowData();
return 0;
}
위의 소스는 컴파일이 안된다. 이유는 id를 초기화 하려고 하는데 id는 const로 설정 되어 있어서 초기화가 되지 않는다.
- 이럴때에는 멤버 이니셜라이저 라는 문법을 사용하면 된다.
- public:
Student(int _id, int _age, char* _name, char* _major) : id(_id)
{
age = _age;
strcpy(name,_name);
strcpy(major,_major);
}
- 위처럼 클래스를 바꿔주면 잘된다. : id(_id)는 멤버 변수 id를 매개 변수 _id로 초기화한다는 뜻이다.
const 멤버 함수
- 멤버 함수가 상수화되면, 이 함수를 통해서 멤버 변수의값이 변경 되는 것은 허용되지 않는다.
- #include <iostream>
- using namespace std;
- class Student
{
const int id;
int age;
char name[20];
char major[30];
public:
Student(int _id, int _age, char* _name, char* _major) : id(_id),age(_age)
{
strcpy(name,_name);
strcpy(major,_major);
} - void ShowData() const
{
cout<<"이름 : "<<name <<endl;
cout<<"나이 : "<<age<<endl;
cout<<"학번 : "<<id<<endl;
cout<<"학과 : "<<major<<endl;
}
}; - int main()
{
Student Kim(1234,23,"l","3");
Student Ho(12315,34,"g","re"); - Kim.ShowData();
cout<<endl;
Ho.ShowData();
return 0;
}
- ShowData 멤버함수를 const 하였다.
- #include <iostream>
- using namespace std;
- class Count
{
int cnt;
public:
Count() : cnt(0){}
int* GetPtr() const{
return &cnt;
}
void Increment()
{
cnt++;
}
void ShowData()const
{
ShowIntro();
cout<<cnt<<endl;
}
void ShowIntro()
{
cout<<"현재 count의 값 : "<<endl;
}
}; - int main()
{
Count count;
count.Increment();
count.ShowData();
return 0;
}
- 위의 클래스부분쪽에 const를 쓴 부분을 보자 int *GetPtr() const 와 ShowData() const에서 오류가 나는데 이유는 const된 함수는 const화 되지 않은 함수의 호출을 허용하지 않을 뿐더러 멤버 변수의 포인터를 리턴하는 것도 허용하지 않는다.
- 출력하려면 어떻게 해야할까? 리턴 받는 값이나 리턴 하는 곳에 const화를 시켜주면 된다.
- class Count
{
int cnt;
public:
Count() : cnt(0){}
const int* GetPtr() const{
return &cnt;
}
void Increment()
{
cnt++;
}
void ShowData() const
{
ShowIntro();
cout<<cnt<<endl;
}
void ShowIntro() const
{
cout<<"현재 count의 값 : "<<endl;
}
};
- 위의 소스 처럼 바꾸면 컴파일이 되긴한다. 저렇게 되는 소스 보다 차라리 const 안쓰는 쪽으로 하는 것이 좋을 것이다.
const와 함수 오버로딩
- 상수 함수냐 아니냐에 따라서도 함수 오버로딩은 성립한다.
- #include <iostream>
- using namespace std;
- class AAA
{
int num;
public:
AAA(int _num):num(_num){}
void ShowData()
{
cout<<"void ShowData(0 호출"<<endl;
cout<<num <<endl;
}
void ShowData() const
{
cout<<"void ShowData() const 호출"<<endl;
cout<<num<<endl;
}
}; - int main()
{
const AAA aaa1(20);
AAA aaa2(70);
aaa1.ShowData();
aaa2.ShowData();
return 0;
}
- const가 있고 없고의 차이로 함수가 달라지는 것을 알 수 있다.
II. 클래스와 static
- 전역 변수가 필요한 상황
- #include <iostream>
- using namespace std;
- int count = 1;
class Person
{
char name[20];
int age;
public:
Person(char* _name,int _age)
{
strcpy(name,_name);
age = _age;
cout<<count++<<"번째 Person 객체 생성 "<<endl; - }
void ShowData()
{
cout<<"이름 : "<<name;
cout<<"나이 : "<<age;
}
}; - int main(void)
{
Person p1("Lee",13);
Person p2("Jong",22);
return 0;
}
위에서 int count =1; 처럼 전역변수로 선언 하면 값이 증가를 한다.
- 완벽한 객체지향적 프로그래밍하기 위해서바꿔 보자.
static 멤버의 특징
- 첫째 main 함수가 호출되기도 전에 메모리 공간에 올라가서 초기화된다. 따라서 public으로 선언이 된다면, 객체 생성 이전에도 접근이 가능하다.
- 둘째 객체의 멤버로 존재하는 것이 아니다. 다만 선언되어 있는 클래스 내에서 직접 접근할 수 있는 권한이 부여된 것이다.
- #include <iostream>
using namespace std; - class AAA
{
public:
static int n;
}; - int AAA::n =1;
- int main()
{
cout<<AAA::n<<endl;
AAA::n++;
cout<<AAA::n<<endl;
return 0;
}
static 멤버는 main 함수가 호출되기 이전에 이미 메모리 공간에 올라가서 초기화된다.
- 초기화를 해주려면 생성자를 써주면 좋겠지만 객체 생성되기 전에 메모리에 올라가기 때문에 int AAA::n = 1; 이런식으로 초기화를 해줘야 한다.
- #include <iostream>
using namespace std; - class AAA
{
int val;
static int n;
public:
AAA(int a =0)
{
val = a;
n++;
}
void ShowData()
{
cout<<"val : "<<val<<endl;
cout<<"n : "<<n<<endl;
}
}; - int AAA::n =1;
- int main()
{
AAA a1(10);
a1.ShowData(); - AAA a2(20);
a2.ShowData();
return 0;
}
위의 소스 결과를 보면 static int n이 private로 선언되어 있기 때문에 외부(main)에서는 허용이 안된다.
- 변수 n은 객체 안에 존재 하지 않는다. 다만 바로 접근할 수 있는 권한이주어져있어서 ShowData에서 접근을 할 수 있는 것이다.
- static 멤버 변수나 멤버함수는 객체의 멤버가 아닌 클래스 변수, 클래스함수라고 표현하는것이 더 정확하다.
그 이외의 키워드 : explicit & mutable
- 명시적인 것만 허용한다! : explicit
- #include <iostream>
using namespace std; - class AAA
{
public:
explicit AAA(int n)
{
cout<<"explicit AAA(int n)"<<endl;
}
}; - int main()
{
AAA a1(10);
AAA a2 = 10;
return 0;
}
위의 소스에서 생성자 AAA 앞에 explicit 키워드를 써서 묵시적인 호출을 허용하지 않게 했다.
- main 함수 안에 AAA a1(10)은 되지만 AAA a2 = 10 은 묵시적으로 AAA a2(10)으로 변환이 되는데 그것을 허용하지 않아서 오류가 난다.
- 예외를 둔다! : mutable
- #include <iostream>
using namespace std; - class AAA
{
private:
mutable int val1;
int val2;
public:
void SetData(int a, int b) const
{
val1 = a;
val2 = b;
cout<<val1<<" "<<val2<<endl;
}
}; - int main()
{
AAA a1;
a1.SetData(10,20);
return 0;
}
public 에 있는 SetData를 const로 지정하여 값을 못 바꾸게 만들고 메인에서 값을 집어 넣으면 원래 val1,val2가 오류가 나야하나 val1에서는 오류가 나지 않는다.
- val1에 mutable를 붙여서 예외로 오류가 안나게 된 것이다. (되도록 안쓰는 편이 좋다.)
'개발 및 관련 자료 > C' 카테고리의 다른 글
[C++] 008. 상속과 다형성 (0) | 2013.05.12 |
---|---|
[C++] 007. 상속(Inheritance)의 이해 (0) | 2013.05.12 |
[C++] 005. 복사 생성자 (0) | 2013.05.12 |
[C++] 004. 클래스의 완성 (0) | 2013.05.12 |
[C++] 003. 클래스의 기본 (0) | 2013.05.12 |
Comments