이것이 C++이다 : Chapter3 내용정리

JB·2022년 5월 11일
0
post-thumbnail

객체지향 프로그래밍

  • 다수의 사용자를 배려하는 코드를 작성해야함 사용자의 편의성을 극대화해야함! 사용자의 실수 가능성을 제작자가 차단!

클래스 기본 문법

  • 선언
    class 클래스이름
    {
    접근제어지시자:
    	멤버변수;
    	멤버함수 선언 및 정의
    };
  • 생성자 : 사용자가 객체를 선언하면 자동으로 호출됨. 반환 자료형이 없고 호출 시기는 자동
    #include <iostream>
    using namespace std;
    
    class CTest{
    public :
        CTest(){//생성자
            m_nData = 10;
        }
    
        int m_nData;
    
        void PrintData(void){
            cout<<m_nData<<endl;
        }
    };
    
    int main(){
        CTest t; //생성자 호출
        t.PrintData();
        
        return 0;
    }
    
    /* 출력결과
    10
    */
     #include <iostream>
    using namespace std;
    
    class CTest{
    public :
        CTest(){//생성자
            cout<<"CTest() : 생성자 호출"<<endl;
            m_nData = 10;
        }
    
        int m_nData;
    
        void PrintData(void);
    };
    
    void CTest::PrintData(void){ //함수 선언, 정의 분리 가능
        cout<<m_nData<<endl;
    }
    
    int main(){
        cout<<"main() 시작"<<endl;
        CTest t;
        t.PrintData();
        cout<<"main() 끝"<<endl;
        return 0;
    }
    /* 출력결과
    main() 시작
    CTest() : 생성자 호출
    10
    main() 끝
    */
    #include <iostream>
    using namespace std;
    
    class CTest{
    public :
        CTest()
            : m_nData1(10), m_nData2(20)//초기화목록
        {
    				//초기화 목록에는 = 안됨
    				//멤버 변수가 참조자 형식이면 반드시 초기화목록 사용
        }
    
        int m_nData1;
        int m_nData2;
    
        void PrintData(void){
            cout<<m_nData1<<endl;
            cout<<m_nData2<<endl;
        }
    };
    
    int main(){
        CTest t;
        t.PrintData();
        return 0;
    }
  • 접근제어 지시자
    • public : 모든 외부 접근 가능

    • protected : 차단. 단, 상속 관계-파생 클래스에서의 접근 허용

    • private : 차단. 클래스 선언 시 별도 기술하지 않으면 private으로 간주

      주의 : 생성자에 접근제어 지시자를 기술하지 않으면 컴파일 오류가 남. 일부러 private으로 선언하는 경우도 있긴 함

생성자와 소멸자

  • 생성자 : constructor, 소멸자 : destructor
  • 클래스와 이름이 같고 소멸자에는 앞에 ~이 붙음
  • 생성자는 다중정의 가능, 소멸자는 안됨. 생성자 위임 지원(아래에 있음!)
  • 디폴트생성자 : 클래스 제작자가 만들지 않아도 컴파일러가 알아서 만듦.(=default 붙여주기)
  • 선언된 블록 범위가 끝나면 자동 소멸
    #include <iostream>
    using namespace std;
    
    class CTest{
    public:
        CTest(){
            cout<<"CTest::CTest()"<<endl;
        }
    
        ~CTest(){
            cout<<"CTest::~CTest()"<<endl;
        }
    };
    
    CTest outmain;
    
    int main(){
        cout<<"main begin"<<endl;
        CTest a;
        cout<<"main end"<<endl;
        return 0;
    }
    /* 출력결과
    CTest::CTest() - outmain
    main begin
    CTest::CTest() - a
    main end
    CTest::~CTest() - a
    CTest::~CTest() - outmain
    */
  • 동적 객체의 생성과 소멸 : new, delete 로 가능. 생성 및 소멸 시점을 명시할 수 있음. 단, 배열로 생성한 객체들은 반드시 배열로 삭제! delete ; → 메모리 릭 버그...
    #include <iostream>
    using namespace std;
    
    class CTest{
        
        int m_nData;
    
    public:
        CTest(){
            cout<<"CTest::CTest()"<<endl;
        }
    
        ~CTest(){
            cout<<"CTest::~CTest()"<<endl;
        }
    };
    
    int main(){
        cout<<"main begin"<<endl;
        CTest* pData = new CTest;
        cout<<"Test"<<endl;
        delete pData;
        cout<<"main end"<<endl;
        return 0;
    }
  • 참조형식 멤버 초기화 : 참조자는 반드시 선언과 동시에 초기화! → 초기화 목록 이용 주의. 참조형식이 아니라 매개변수 대입연산으로 초기화하게 되면 함수 내부의 자동 변수와 같으므로 함수가 반환될 때 매개변수가 소멸되어 이상한 값이 출력됨!
    #include <iostream>
    using namespace std;
    
    class CRefTest{
    public:
        CRefTest(int &rParam) : m_nData(rParam){};
        int GetData(void){return m_nData;};
    
    private:
        int &m_nData;
    
    };
    
    int main(){
        int a = 10;
        CRefTest t(a);
        cout<<t.GetData()<<endl;
    
        a = 20;
        cout<<t.GetData()<<endl;
    
        return 0;
    }
    /* 출력 결과
    10
    20
    */
  • 생성자 다중정의 - 생성자 위임
    #include <iostream>
    using namespace std;
    
    class CMyPoint{
    public:
        CMyPoint(int x){
            cout<<"CMyPoint(int)"<<endl;
    
            if(x>100){
                x = 100;
            }
            m_x = 100;
        }
    
        CMyPoint(int x, int y)
        : CMyPoint(x) //CMypoint(int) call
        {
            cout<<"CMyPoint(int, int)"<<endl;
            cout<<x<<endl;
    
            if(y>200){
                y = 200;
            }
            m_y = 200;
        }
    
        void Print(){
            cout<<"X : "<<m_x<<endl;
            cout<<"Y : "<<m_y<<endl;
        }
    
    private:
        int m_x = 0;
        int m_y = 0;
    };
    
    int main(){
        CMyPoint ptBegin(110);
        ptBegin.Print();
    
        CMyPoint ptEnd(50, 250);
        ptEnd.Print();
    }
    /*출력결과
    CMyPoint(int)
    X : 100
    Y : 0
    CMyPoint(int)
    CMyPoint(int, int)
    50
    X : 100
    Y : 200
    */

메서드

메서드 : 클래스의 멤버 함수(메서드를 통해 멤버변수를 제어할 수 있으므로 ‘인터페이스 함수'라고도 불림)

static 반환자료형 클래스이름::함수이름(매개변수) const;
//static, const 생략 가능
  • 정적 메서드는 this 포인터 접근이 불가능함.

  • this 포인터 : 작성 중인 클래스의 실제 인스턴스에 대한 주소! : 명시를 통해 사용자 실수를 줄임

정적 멤버

  • 전역함수는 불필요한 의존 관계를 만듦 → 정적 멤버!
  • 정적 멤버 : 전역 멤버와 같으나 클래스 멤버로 들어와있어 소속이 확실함!
  • 인스턴스 선언 없이 정적 멤버 함수 호출 가능하지만 this포인터는 사용할 수 없음.
  • 정적 멤버 변수는 반드시 선언과 정의를 분리해야함.
#include <iostream>
using namespace std;

class CTest{
public:
    CTest(int nParam)
    :m_nData(nParam){
        m_nCount++;
    }
    int GetData(){
        return m_nData;
    };
    void ResetCount(){
        m_nCount = 0;
    };
    static int Getcount(){
        return m_nCount;
    };

private:
    int m_nData;
    static int m_nCount;    
};

int CTest::m_nCount = 0;

int main(){
    CTest a(5), b(10);
    cout<<a.Getcount()<<endl;
    b.ResetCount();

    cout<<CTest::Getcount()<<endl;
    return 0;
}
/*출력결과 : 전역변수처럼 사용됨.
2
0
*/
profile
자율주행 이동체를 배우고 있는 JB입니다.

0개의 댓글