티스토리 뷰

LANGUAGE/C++

[C++] CLASS

진심스테이크 2018. 3. 7. 09:59

 

클래스 : 추상적인 것을 객체화 시킨 것

#객체 :  사람이 정의할 수 있는 모든 것

 

절차 지향 : 순서에 의해서 진행 -> C 스타일

객체 지향 : 확장성, 유지보수성이 가장 중요!

 

 

기본 형태

class 클래스 이름 {

//내용

}; //세미 콜론 필수!

 

 

클래스 안에 들어가야할 내용

1. Member variable - 멤버 변수 // Field

2. Member function - 멤버 함수 // Method

3. Constructor - 생성자

 

 

default로 정의되는 함수

  1. 생성자 함수 : 객체 등록 시 자동으로 호출되어지는 함수

- 역할

  ㉠ 객체 필드 초기화 -> 쓰레기 값 방지

  ㉡ 객체 등록 -> default

- 접근 지정자는 주로 public을 사용 ( 필수는 아님 ) -> 외부 함수에서 객체를 만들기 때문

- 오버로딩 가능 ( 명시적 / 암시적 )

- const member function으로 만들 수 없다

- 리턴 타입이 없다

- 함수 이름이 클래스 명과 동일하다

- default 생성자 함수는 생성자 함수를 명시적으로 제공하지 않을 경우에만 제공된다

 

#const : 고정

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
using namespace std;

class A {
    //생성자 함수
public : //명시한 순간부터 다른 접근 지정자를 만나기 전 or 끝까지 접근 지정자가 같다
         //접근 지정자를 명시하지 않으면 자동으로 private으로 지정된다

    int a;
    int *p; //필드 초기화 = 메모리 할당
    int b[];

    A() {
        a = 0;
        cout << "나는야 생성자 " << a << endl;
    }

    //명시적 오버로딩
    //단순하게 값만 달라지는 경우에는 쓸 필요가 없다
    A(int i) {
        a = i;
        cout << "두번째 생성자 " << a << endl;
    }

    //암시적 오버로딩
    A(int i = 0) {
        a = i;
        cout << "디폴트 매개 변수 사용 " << a << endl;
    }

    //동적 메모리 할당 -> 크기가 i인 배열을 가리킨다
    A(int i = 1) { //배열은 0으로 지정해줄 수 없음
        a = i;
        p = new int[i];
    }
};

void main() {
    //정적 메모리 -> stack
    A aa; //객체 생성

    //동적 메모리
    A *p = new A; //A()가 아닌 이유는 아무것도 지정해주지 않았기 때문

    //명시적 오버로딩
    A a(10);

    //암시적 오버로딩
    A bb(5);

    //동적 메모리 할당
    A c;
    A cc(9);
}

 

  2. 복사 생성자 함수

- 복사 생성자가 생성되는 경우

  ㉠ 객체 생성시 매개 변수로 객체를 명시할 때

      ex) A aa; // 생성자 호출

            A bb(aa); // 복사 생성자 호출

  ㉡ 객체 생성시 객체를 대입 할 때

      ex) A aa; // 생성자 호출

            A bb = aa; // 복사 생성자 호출

  ㉢ 멤버 함수에 매개 변수로 객체를 선언 할 때

            ex) void A::disp( A aa ) // 복사 생성자 호출

  ㉣ 멤버 함수에서 객체를 리턴 할 경우

      ex) A getObject() {

return 객체 // 복사 생성자 호출

}

- 기본 형태

  A( const A &aa ) {

//내용

  }

- 생성자의 기본 역할인 등록 역할도 한다

- 객체는 모든 멤버의 값을 복사하는 기능을 제공한다

  ㉠ 얕은 복사 : 디폴트가 기본적으로 제공이 된다]

  ㉡ 깊은 복사 : 개발자가 꼭 명시적으로 만들어야 한다 -> 필드를 포인터로 사용했을 때, 무조건 사용

- 접근 지정자는 public을 사용

 


   

얕은 복사

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
using namespace std;

class A {
    //복사 생성자 - 얕은 복사
    int a;
    int b;
public :
    A(int a = 0, int b = 0) {
        this->a = a;
        this->b = b;
    }
    A(const A& ii) { //복사 생성자
        cout << "복사 생성자" << endl;
        //디폴트
        a = ii.a;
        //ii.a는 bb의 a값, 즉 10
        //a는 cc의 a값
        //결론은, bb의 a값을 cc의 a값에 넣겠다라는 뜻
        b = ii.b;
    }
    void setA(int a) { this->a = a; }
    void setB(int b) { this->b = b; }
    int getA() { return a; }
    int getB() { return b; }
};

void main() {
    A bb(10, 20);
    A aa;

    cout << aa.getA() << "\t" << aa.getB() << endl; //0,0
    cout << bb.getA() << "\t" << bb.getB() << endl; //10,20

    A cc(bb); //복사 생성자 호출
    cout << cc.getA() << "\t" << cc.getB() << endl; //10,20
}

 

깊은 복사

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
using namespace std;

class A {
    //복사 생성자 - 깊은 복사
    int *p;
    int *p1;
public :
    A(int i = 0) {
        p = new int;
        *p = i;
    }
    
    A(const A& ii){ //복사 생성자
        p = new int; //bb의 값을 넣어줄 공간을 할당해줌
        *p = *ii.p; //값 복사 -> 안하면 오류
    /*오류 이유 : aa도 10을 가리키고, bb도 10을 가리키는 상태에서 소멸자를 실행하면,

                bb가 stack구조로 인해 먼저 지워지게 된다
                그러면 둘다 가리키는 10이 지워지기 때문에 aa는 소멸시킬 값이 없어지게 된다
    */
    }
    
    ~A() { //메인이 끝날 때 불러줌
        cout << *p << endl;
        delete p;
    }

    int getP() { return *p; }
};

void main() {
    //정적메모리 - stack : First In Last Out
    //bb를 먼저 꺼내고 aa를 꺼낸다
    A aa(10);
    A bb(aa); //복사 생성자 호출
    cout << bb.getP() << endl;
}

 


 

  3. 소멸자 함수 : 객체 소멸시 자동으로 호출되어지는 함수

- 클래스를 통 틀어서 하나만 존재

- 정적 메모리 : 함수가 끝날 때 사라진다

- 동적 메모리 : delete 호출 -> 호출하지 않으면 소멸되지 않는다

- 기본 형태

  ~클래스명( ) { }

- 매개 변수를 선언할 수 없다 -> 오버로딩 불가능

- const member function으로 만들 수 없다

- 객체의 잔여 메모리를 깨끗하게 정리하는 역할을 한다 -> 개발자가 직접 해줘야 한다

- 가상함수로 만들어야 한다 -> 동적 바인딩을 하기 위함

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
using namespace std;

class A {
    //소멸자
public :
    //생성자와 소멸자는 한쌍
    A() { cout << "생성자" << endl; }
    ~A() { cout << "소멸자" << endl; }
};

void main() {
    A aa;
}

 

 

  4. 대입 연산자 함수

 

 

 


 

접근 지정자

1. public : 모두 접근 가능

2. private : 자기 클래스 내에서 사용 가능

   - C++에서 외부에서 접근 허용을 가능한 경우가 있다 (캡슐화 파기 가능 - friend)

   - static : 다른 클래스에서 private 클래스 안에 있는 메소드를 사용하고 싶을 때, 메소드를 static으로 선언해준다

3. protected : 클래스 내에서 접근 가능, 상속 받은 자식 클래스만 접근 가능

 

생성자의 역할 : 필드 초기화

필드를 포인터로 지정 = 동적 메모리를 할당

 

#JAVA에서는 생성자가 디폴트이지만 C++은 아니다.

#외부 함수 : 클래스 밖에서 생성하는 함수

 

'LANGUAGE > C++' 카테고리의 다른 글

[C++] STATIC  (0) 2018.03.08
[C++] THIS  (0) 2018.03.08
[C++] OVERROADING  (0) 2018.03.06
[C++] POINTER ARRAY - 포인터 배열  (1) 2018.03.06
[C++] DYNAMIC MEMORY - 동적 메모리  (0) 2018.03.06
댓글