ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 윤성우 열혈 C++ 프로그래밍 4장) 클래스의 기본(정보은닉, const함수, 이니셜라이져, 생성자, 소멸자, this포인터, self-reference)
    PROGRAMMING/C++ 2023. 12. 28. 08:02

    개미는 뚠뚠 오늘도 뚠뚠 열심히 공부하네 뚠뚠 🐜

     

    (혹시 저작권에 문제가 있다면 수정하겠습니다!! 개인적인 공부용으로 정리함을 알려드립니당)

     

    https://product.kyobobook.co.kr/detail/S000001589147

     

    윤성우의 열혈 C++ 프로그래밍 | 윤성우 - 교보문고

    윤성우의 열혈 C++ 프로그래밍 | 『C++ 프로그래밍』은 C언어를 이해하고 있다는 가정하에서 집필된 C++ 기본서로서, 초보자에게 적절한 설명과 예제를 통해서 C++ 프로그래밍에 대해 설명한다. 더

    product.kyobobook.co.kr

     

    정보은닉

    : 멤버변수를 private으로 선언하고, 해당 변수에 접근하는 함수를 별도로 정의해서 안전한 형태의 멤버변수의 접근을 유도

    → 제한된 방법으로의 접근만 허용해야 잘못된 값이 저장되는 것을 막을 수 있고, 실수도 쉽게 발견할 수 있다.

     

    엑세스 함수들(Get, Set 등) 호출되지 않을지라도 필요하다고 판단될 경우 포함하는 경우가 많다.

    // 엑세스 함수(access function)
    int GetX() const;
    bool SetX(int xpos);

     

    const함수

    클래스 내 함수에서의 의미 : 이 함수 내에서는 멤버변수에 저장된 값을 변경하지 않겠다. 

    - const 함수 내에서는 const 함수가 아닌 함수의 호출이 제한된다. 

    (참조자도 마찬가지로 const 참조자를 이용하는 경우 const 함수만 호출 가능하다.)

     

    캡슐화 : 관련 있는 함수와 변수를 하나의 클래스 안에 묶는 것

     

    생성자

    - 클래스의 이름과 함수의 이름이 동일

    - 반환형 X

    - 객체 생성시 딱 한 번 호출된다.

    - 함수의 일종이므로 오버로딩이 가능하며, 매개변수에 디폴트 값을 설정할 수 있다.

     

    class CLASS{
    private:
    	int num1; 
        char ch1;
    public:
    	CLASS(){num1 = 1; ch1 = 'c';}
        CLASS(int n){num1 = n; ch1 = 'c';}
        CLASS(int n, char ch){num1 = n; ch1 = ch;}
    }

     

    (아니 이거 간격 왜이러실깡..)

     

    위에서 정의한 생성자를 이용하면 다음과 같은 방식으로 객체를 생성할 수 있다.

    //두번째 생성자
    CLASS cl(100);
    CLASS * ptr = new CLASS(100);
    
    //세번째 생성자
    CLASS cl(100, 'c');
    CLASS * ptr = new CLASS(100, 'c');
    
    CLASS cl();                // (X)
    CLASS cl;                 // (O)
    CLASS * ptr = new CLASS;  // (O)
    CLASS * ptr = new CLASS();// (O)

     

    //CLASS cl()이 안되는 이유
    
    CLASS cl(){
    	CLASS cl(100, 'c');
        return cl;
    }
    
    // 객체새성문과 함수의 원형선언을 구분하지 못함

     

    맴버 이니셜라이져(Member Initializer)

    class Rectangle
    {private:
    	Point upLeft;
        Point lowRight;
        int n;
    pubblic: 
    	Rectangle(const int &x1, const int &x2, const int &y1, const int &y2, const int &_n);
    };
    
    Rectangle::Rectangle(const int &x1, const int &x2, const int &y1, const int &y2, const int &_n)
    : upLeft(x1, y1), lowRight(x2, y), n(_n)
    {
    //empty - 종종 생성자 몸체 부분이 empty이기도 함
    }

    여기서 :upLeft(x1, y1), lowRight(x2, y2), n(_n)이 맴버 이니셜라이져이다.

    특히 n(_n)은 1. 초기화의 대상을 명확히 인식할 수 있고 2. 성능에 이점이 있다는 점에서 선호되는 표기법이다.

     

    이니셜라이저를 이용하면 선언과 동시에 초기화가 이뤄지는 형태로 바이너리 코드가 생성된다.

     

    const 맴버변수참조자도 이니셜라이저를 통해 초기화할 수 있다‼️

     

    디폴트 생성자

    객체의 생성과정

    1. 메모리 공간 할당

    2. 이니셜라이져 → 맴버변수의 초기화

    3. 생성자의 몸체부분 실행

    이 과정에서 생성자는 반드시 호출된다. 우리가 생성자를 호출하지 않으면 디폴트 생성자가 자동으로 호출된다.

    class AAA{
    private:
    	int num;
    private :
    	AAA(){} // 디폴트생성자
    };

     

    - 모든 객체는 한번의 생성자를 호출하는데, new 연산자를 이용한 객체 형성에서도 생성자가 호출된다.

    하지만 malloc함수를 이용하면 생성자는 호출되지 않는다.(AAA클래스 크기 정보만 바이트 단위로 전달하기 때문)

    → 객체를 동적하는 경우 new 연산자를 이용하자!!!!!

     

    - 디폴트 생성자는 생성자가 정의되지 않았을 때에만 삽입된다. (생성자가 이미 있는 경우 삽입되지 않는다)    

    class SoSimple{
    private :
    	int num;
    public : 
    	SoSimple(int n) : num(n){}
    }
    
    // 객체 가능한 형태
    SoSimple obj1(10);
    SoSimple * obj2 = new SoSimple(10);
    
    // 객체 새성 불가능한 형태
    SoSimple obj3;
    SoSimple * obj4 = new SoSimple;

    이 경우 아래의 생성자를 추가해야 한다.

    SoSimple() : num(0){}

     

    private 생성자 : 객체의 생성방법을 제한하고자 하는 경우 매우 유용하다.

    (딴게 아니고 생성자를 private : 선언 안에 넣어둠)

     

    소멸자

    - '~클래스 이름'의 형태

    - 반환형 X

    - 매개변수 = void형 이므로 오버로딩 불가, 디폴트 값 설정 불가

    class Person{
    private :
    	char * name;
    	int age;
    public:
    	Person(char * myname, int myage) // 생성자
        {  
    		int len = strlen(myname) + 1;
        	name = new char[len];
        	strcpy(name, myname);
        	age = myage;
    	}
    	~Person() // 소멸자
        {
        	delete []name;
        }

     

    객체배열과 객체 포인터 배열 - 객체를 저장하는 두가지 방법

    [객체배열]

    동적으로 객체 배열을 선언하면 호출할 생성자를 별도로 지정하지 못한다.

    SoSimple * ptrArr = new SoSimple[100];

    즉, 객체 배열이 생성되려면 반드시 아래와 같은 생성자가 반드시 정의되어 있어야 한다.

    SoSimple(){...}

    배열선언 이후에 각각의 요소를 원하는 값으로 초기화 하려면 일일히 초기화해야한다.

     

    [객체 포인터 배열]

    Person * parr[3];
    
    for(int i = 0; i<3; i++){
    	parr[i] = new Person(namestr, age);
    }
    
    ~
    
    for(int i = 0; i<3; i++){
    	delete parr[i];
    }

     

    this 포인터의 이해

    this 포인터 : 객체 자신을 가리키는 용도로 사용되는 포인터(객체자신의 주소값) 

    class Thisclass{
    private : 
    	int num;
    public :
    	Thisclass(int num)
        {
        this->num = num;
        }
    };

    this->num은 맴버변수를 의미하므로, 맴버변수와 매개변수를 this의 유무로 구분할 수 있다. 

     

    Self-Reference의 반환

    Self-Reference : 객체 자신을 참조할 수 있는 참조자(return 값을 *this로)

    class Thisclass{
    private : 
    	int num;
    public :
    	Thisclass(int num)
        {
        this->num = num;
        }
        
        Thisclass& Adder(int n) // 객체 자신의 참조의 정보 반환
        {
        	num += n;
            return *this;  // 객체 자신을 반환
         }
    };

     

    참조자 : 대입연산자의 왼편 & 또는 반환형으로 & 선언시 참조의 정보 전달

     

     

    댓글

Designed by Tistory.