[ 7주차 - 1 ]
클래스 멤버 변수에 초기값 ( 멤버 함수 이용 )
#include <iostream>
using namespace std;
class myclass {
private:
int a; // 전용데이터
public:
int b; // 공용 데이터
void setab(int i); // 공용 함수
int geta();
void reset();
};
void myclass::setab(int i) {
a = i; //a를 직접 참조
b = i * i; // b를 직접 참조
}
int myclass::geta() {
return a;
}
void myclass::reset() {
setab(0); // 다른 멤버 함수를 호출하는 것도 가능
}
int main(){
myclass ob; //ob 객체 생성
ob.setab(10,20); //초기값 넣어주기
}
myclass에서는 멤버 변수와 멤버 함수를 선언하는 것이고 main 함수에서 myclass ob;를 실행해주면 메모리에
ob라는 myclass 객체가 생성이 되고 a,b 멤버 변수와 멤버 함수가 할당이 된다. myclass를 선언하는 시점에서는
메모리에 할당이 되지 않는다. 초기값은 메모리가 할당된 상태에서 넣어주는 것 이기 때문에 선언하는 시점에서
a,b에 초기값을 주게 되면은 컴파일 에러가 난다.
즉 ob라는 myclass 객체가 생성되는 시점에 메모리에 할당되는 것이기 때문에 멤버 변수에 초기값을 넣어줄 수 있다.
초기값을 넣어주기 위해 setab 멤버 함수를 선언을 하고, 인자로 받은 값을 멤버 변수에 넣어서 초기값을
넣어줄 수 있다. 초기값을 넣어주는 멤버 함수를 선언하고 메인 함수에서 객체를 선언하고 그 객체에 초기값을
넣어주는 함수를 호출함으로써 멤버 변수에 초기값을 넣어줄 수 있다. 클래스를 선언할 때는 멤버 변수에 초기값을
넣어주면 에러가 난다.
생성자와 소멸자
생성자 함수의 이름은 클래스 이름과 동일하다. 또한 리턴 타입이 없고, 생성자 안에는 return문이 있으면 안된다.
소멸자 함수는 생성자 함수에 ~를 붙여주면 된다. 클래스를 정의해주면비주얼 스튜디오가 알아서 헤드 파일안에
생성자와 소멸자를 정의해둔다.
#include <iostream>
using namespace std;
class queue {
int q[100];
int sloc, rloc;
public:
queue(); // 생성자
~queue(); // 소멸자
void qput(int i);
int qget();
};
queue::queue() { // 생성자
sloc = rloc = -1; // 초기값
cout << "Queue initialized.\n";
}
queue::~queue() { // 소멸자
cout << "Queue destroyed.\n";
}
생성자 함수 부분에는 보통 멤버 변수에 대해서 초기값을 부여해주는 실행문을 포함하고 있다.
소멸자 함수는 동적 메모리를 할당해서 사용했을 때 동적 메모리를 없애주거나, queue 클래스의 객체가 없어질 때
자동으로 실행된다.
생성자는 메인 함수에서 queue 클래스의 객체를 선언해서 생성할 때 자동으로 생성자 함수가 실행이 된다.
소멸자는 해당하는 클래스의 객체가 사라질 때 자동으로 실행이 된다.
qput()과 qget()은 해당하는 클래스의 객체를 생성하고 .을 이용해서 직접 호출해줘야 하지만 생성자와 소멸자는
자동으로 호출이 된다. 즉 생성자와 소멸자는 특별한 함수이다.
void queue::qput(int i) { // 하나의 정수를 큐에 저장한다.
if (sloc == 99) {
cout << "Queue is full.\n";
return;
}
sloc++;
q[sloc] = i;
}
int queue::qget() { // 큐에서 하나의 정수를 얻는다.
if (rloc == sloc) {
cout << "Queue underflow.\n";
return 0;
}
rloc++;
return q[rloc];
}
int main() {
// 두 개의 queue 객체를 생성한다.
queue a, b;
a.qput(10);
b.qput(19);
a.qput(20);
b.qput(1);
cout << a.qget() << " ";
cout << a.qget() << " ";
cout << b.qget() << " ";
cout << b.qget() << " ";
return 0;
}
main 함수에서 2개의 queue 객체를 생성하면 a,b 객체 각각에 크기가 100인 배열이 할당이 되고 sloc, rloc 변수가
각각 할당이 된다. 그리고 제일 먼저 생성자 함수가 실행이 되서 a,b 객체의 sloc과 rloc에 -1을 넣어준다.
//▶ Queue initialized.
// Queue initialized.
// 10 20 19 1
// Queue destroyed.
// Queue destroyed.
첫번째 Queue initialized는 a 객체의 생성자 함수이고, 두번째 Queue initialized는 b 객체의 생성자 함수이다.
그리고 a,b가 가지고 있는 각각의 q 배열에 qput()을 사용해서 값을 넣어준다.
리턴문을 만나서 main() 함수가 종료가 되면 a,b 객체가 사라지게 되고 자동으로 소멸자 함수가 실행된다.
첫번째 Queue destroyeds는 a 객체의 소멸자 함수이고, 두번째 Queue destroyed는 b 객체의 소멸자 함수이다.
생성자와 소멸자는 클래스를 사용할 때 특별한 작업을 수행해준다. 메인 함수에서 생성자, 소멸자 함수를 직접적으로
호출하지 않는다. 즉 자동 호출된다.
매개 변수를 갖는 생성자
객체의 생성자에게 인수 전달 : 객체가 생성될 때 멤버 변수들에게 프로그램에서 정의된 초기값을 줄 수 있게 한다.
#include <iostream>
using namespace std;
class queue {
int q[100];
int sloc, rloc;
int who; // 큐의 ID 번호를 저장한다.
public:
queue(int id); // 매개변수를 갖는 생성자
~queue(); // 소멸자
void qput(int i);
int qget();
};
queue::queue(int id) { // 생성자
sloc = rloc = -1;
who = id;
cout << "Queue" << who <<"initialized.\n";
}
반드시 매개변수를 가져야 하는 것은 아니지만 queue 클래스의 멤버 변수에 초기값으로 생성자의 매개 변수로 받은
값을 넣어줘야할 필요가 있다면 생성자에 매개 변수를 선언하면 된다.
// 생성자에 인수 전달
// 객체 생성시
queue a(1), b(2);
// 다른 형식
queue a = queue(1); // 사용안함
매개 변수를 갖지 않을 경우는 queue a,b;로 선언해주면 되지만 생성자 함수가 매개변수를 갖을 경우에는 매개변수에
전달할 인수값을 ()안에 명시해주면 된다. queue a(1);로 명시를 해주면 1이 생성자 함수의 id로 전달이 되고
who 변수에 저장된다. 생성자 함수가 매개변수를 갖고 있다면, 매개 변수에 전달할 값을 반드시 명시해줘야 한다.
( 상수를 넣어주든 변수를 넣어주든 상관없음 ) 명시해주지 않으면 컴파일 에러가 난다.
클래스 멤버 변수에 초기값 ( 생성자 이용 )
생성자 함수를 이용해서 멤버 변수에 초기값을 설정해줄 수 있다. 소멸자 함수는 잘 명시하지 않는다.
소멸자 함수를 사용하는 경우는 클래스의 멤버 함수에서 동적 메모리를 생성하고 해제하지 않는 경우에 보통
소멸자에서 해제하기 위해 사용한다. 하지만 보통 소멸자 함수는 아무것도 포함하고 있지 않다.
#include <iostream>
using namespace std;
class myclass {
private:
int a;
int b;
public:
// void setab(int i,int j); ->불필요
int geta();
void reset();
myclass(int i, int j); // 매개변수를 갖는 생성자
};
myclass::myclass(int i, int j) {
a = i; //a에 i를 치환
b = j; //b에 j를 치환
}
int myclass::geta() {
return a; //a를 직접 참조
}
void myclass::reset() {
}
int main() {
myclass ob(10,20); //ob의 멤버 변수 a,b에 초기값
//ob.setab(10, 20); -> 바로 파라미터로 명시해주면 setab 멤버 함수를 호출할 필요 없음
}
클래스와 구조체 차이
c++에서는 구조체 역시 객체 지향적인 성질을 가진다. → 클래스와 구조체가 상호 교환이 가능하다.
구조체는 관련된 메모리들을 묶어서 struct을 사용해서 관리하는 하나의 도구이다. struct은 메모리만 갖고 있는다.
반면에 클래스는 메모리를 가지고 있을 뿐만 아니라 메모리에 동작하는 함수들도 가지고 있는다.
즉 클래스가 구조체보다 더 융통성이 있다. 그래서 구조체를 잘 사용하지 않는다.
* 한가지 예외로 잠정적으로 클래스 멤버들은 private인 반면, 구조체 멤버들은 public이다.
인라인 함수
인라인 함수 : 함수의 호출 지점에서 함수의 코드가 라인으로 확장되는 함수
함수를 호출할 때 인수 저장과 함수 복귀 등을 위한 명령이 필요한데, 인라인 함수는 이러한 지체가 없어 프로그램이
효율적이다. 인라인 함수가 큰 경우에는 프로그램의 전체 크기가 증가한다. → 크기가 큰 함수는 보통 정상적인
함수로 사용
* 인라인은 잘 사용되지 않음.
< 함수 생성 방법 >
ⓐ inline 수정자를 사용
ⓑ 멤버 함수에 대한 코드를 클래스 선언 안에서 정의 ( 키워드 inline을 선언 앞에 붙일 필요가 없다. )
#include <iostream>
using namespace std;
class cl {
private:
int i; // 잠정적으로 전용 멤버
public:
int get_i();
void put_i(int j);
};
inline int cl::get_i() {
return i;
}
inline void cl::put_i(int j) {
i = j;
}
int main() {
cl s;
// 호출되지 않고 라인으로 확장
s.put_i(10);
cout << s.get_i();
return 0;
}
< 클래스 안에서 코드 정의하기 >
#include <iostream>
using namespace std;
class cl {
private:
int i; // 잠정적으로 전용 멤버
public:
// 구현부분을 명시하지 않고 자동적으로 인라인 함수로 취급
int get_i() { return i; };
void put_i(int j) { i = j; };
};
int main() {
cl s;
// 호출되지 않고 라인으로 확장
s.put_i(10);
cout << s.get_i();
return 0;
}
실습문제
하나의 문자열을 멤버 변수로, 그 문자열과 관련된 문자열 함수를 갖는 클래스를 선언하고, 메인 함수에서
이 클래스의 객체를 생성해서 실행하기
* C에서는 문자열 리터럴이 char 배열이지만, C++에서는 const char 배열이다.
* 문자열을 복사할 경우에는 strcpy_s를 사용해야한다.
#include <iostream>
using namespace std;
class mystring {
private:
char str[80]; //하나의 문자열
public:
mystring(const char *s); // 생성자, 매개변수의 s 문자열을 str에 저장하기
int strlength(); // str에 저장된 문자열의 길이를 반환
int numchar(char ch); //str에 포함된 문자 ch의 개수를 반환
};
mystring::mystring(const char *s) {
strcpy_s(str, s);
//strcpy_s 함수를 이용해서 문자열을 복사해야한다.
}
int mystring::strlength() {
return strlen(str);
}
int mystring::numchar(char ch) {
int count = 0;
for (int i = 0; i < strlength(); i++) {
if (str[i] == ch ) {
count++;
}
}
return count;
}
int main() {
mystring my("I am studing C++ Language.");
cout << "문자열 길이 : " << my.strlength();
cout << " 문자 a의 개수 : " << my.numchar('a');
}
//▶ 문자열 길이 : 26 문자 a의 개수 : 3'2CHAECHAE 학교생활 > 객체지향프로그래밍(C++)' 카테고리의 다른 글
| [ 객체지향프로그래밍(C++) 9주차 ① ] (0) | 2022.05.01 |
|---|---|
| [ 객체지향프로그래밍(C++) 7주차 ② ] (0) | 2022.04.16 |
| [ 객체지향프로그래밍(C++) 6주차 ② ] (0) | 2022.04.11 |
| [ 객체지향프로그래밍(C++) 6주차 ① ] (0) | 2022.04.11 |
| [ 객체지향프로그래밍(C++) 5주차 ② ] (0) | 2022.04.01 |