뚜둔뚜둔✩

판다의 개발일지

C · C++

[C++] 구조체(struct)와 클래스(class)

2022. 5. 15. 23:42

    구조체

    여러 데이터 값을 갖는 어떤 새로운 타입을 정의할 때 흔히 구조체를 사용한다.

    C 언어에서의 구조체는 실제 데이터만을 포함하지만 C++에서는 데이터뿐만 아니라 생성자, 소멸자, 멤버 함수, 접근 지정자를 포함할 수 있다는 것이 다르다.

     

    [ C언어 ]

    struct Point
    {
    	int x;
        int y;
    };

    [ C++ ]

    struct Point
    {
    private:
    	int x;
        int y;
    
    public:
    	Point() {}
        ~Point() {}
        
        int getX(void) { return x; }
        int getY(void) { return y; }
    };

     

    접근 지정자

    C++ 구조체는 접근 지정자로 특정 멤버 변수 및 함수를 외부에서 접근할 수 없게 할 수 있다.

    private 접근 지정자는 외부에서의 접근을 막으며, public 접근 지정자로 선언된 멤버는 모든 접근이 가능하다.

    include <iostream>
    
    struct Point
    {
    private:
    	int x;
    	int y;
    };
    
    int main(void)
    {
    	Point p1;
    
    	std::cout << p1.x << std::endl;
    
    	return 0;
    }

    위의 코드에서처럼 private 멤버를 접근했을 때에는 다음과 같이 컴파일이 실패하게 된다.

    main.cpp:14:18: error: 'x' is a private member of 'Point'
            std::cout << p1.x << std::endl;
                            ^
    main.cpp:6:6: note: declared private here
            int x;
                ^
    1 error generated.

    구조체와 클래스의 차이

    C++에는 class(클래스)라는 키워드가 새로 도입되었는데, 그 형태와 기능은 구조체와 거의 동일하나 접근 지정자의 기본 설정이 다르다.

    특히나, 접근 지정자가 생략되었을 때 default로 설정되는 키워드가 다르다.

    접근 지정자 생략 시 구조체 (struct) 클래스 (class)
    public private

    또, 클래스에는 상속의 개념이 있다. (객체 지향 프로그래밍) C++에서는 구조체 역시 클래스와 마찬가지로 상속이 되지만, 접근 지정자의 기본 설정이 앞서 설명한대로 유지된다.

    이러한 상속 관계에서는 또 다른 접근 지정자인 protected가 있다. protected 접근 지정자의 멤버는 자신과 상속받은 클래스의 멤버 및 friend에서 접근할 수 있다.

    접근 지정자 설명
    private ・ 외부에서 접근할 수 없다.
    ・ 자신의 멤버 함수 및 friend에서만 접근할 수 있다.
    public ・ 접근에 제한이 없다.
    protected ・ 자신의 멤버 함수 및 friend에서만 접근할 수 있다.
    ・ 파생 클래스의 멤버 함수 및 friend에서만 접근할 수 있다.

    friend 함수와 클래스

    계속해서 friend 라는 개념이 등장하는데, friend 함수는 원래는 외부에서 접근이 막힌 멤버에 대한 접근이 가능하다. 앞서 private 멤버 Point.x에 접근해 컴파일 실패했던 코드를 friend 함수를 통해 접근하게 변경하면 컴파일에 성공한다.

    class Point
    {
    private:
    	int x;
    	int y;
    
    	friend int getX(Point &p);
    };
    
    int getX(Point &p)
    {
    	return p.x;		// friend functions can access private members
    }
    
    int main(void)
    {
    	Point p1;
    
    	std::cout << getX(p1) << std::endl;
    
    	return 0;
    }

    또, friend로는 함수뿐만 아니라 friend 클래스도 있다.

    class Point
    {
    	friend class Map;
    
    private:
    	int x;
    	int y;
    };
    
    class Map
    {
    public:
    	int getDistance(Point &p1, Point &p2)
    	{
    		return (p1.x > p2.x) ? (p1.x - p2.x) : (p2.x - p1.x);
    	}
    };

    Point 클래스 내 Map 클래스를 friend 클래스로 선언하지 않는다면 컴파일 시 private 멤버 접근으로 인한 에러가 발생한다.

     

    생성자 (Constructor)

    생성자는 어떤 객체의 생성 시 자동으로 호출되는 함수이다. 따라서 초기화에 필요한 동작을 별도의 초기화(init) 함수를 생성하는 대신 생성자에서 수행하게 하면 init(초기화) 함수를 따로 호출해줄 필요가 없다.

    class Point
    {
    public:
    	Point() {}
    }

    생성자의 특징은 다음과 같다.

    ・ 함수 이름이 클래스 이름과 완전히 동일해야 한다.
    ・ 별도로 리턴하는 값이 없으며, 함수 선언시 리턴 타입 자체를 표기하지 않아야 한다.
    ・ 생성자는 0개 이상의 인자를 가지며, 오버로딩으로 여러개의 생성자를 선언할 수 있다.

    생성 시 자동으로 호출되기 때문에 최소한 1개의 생성자가 반드시 있어야 한다. 하지만 생성자가 없는 class가 컴파일이 안 되는 것은 아닌데, 그 이유는 생성자가 하나도 선언되지 않았다면 아무것도 하지 않는 생성자를 컴파일러가 자동으로 추가하기 때문이다.

     

    소멸자 (Destructor)

    소멸자는 어떤 객체가 파괴될 때 호출되는 함수로, 특히나 동적으로 할당받은 자원을 객체 파괴 시 해지하는 목적으로 사용된다.

    class Point
    {
    public:
    	~Point() {}
    }

    소멸자의 특징은 다음과 같다.

    ・ 함수 이름이 클래스 이름과 완전히 동일해야 하며, 함수 이름 앞에 "~"가 붙는다.
    ・ 별도로 리턴하는 값이 없으며, 함수 선언시 리턴 타입 자체를 표기하지 않아야 한다.
    ・ 소멸자는 0개의 인자를 갖는다. 따라서 오버로딩이 불가능하다.
    ・ 사용자가 소멸자를 별도로 생성하지 않는 경우 컴파일러로 인해 자동 생성된다.

     

    'C · C++' 카테고리의 다른 글

    [C++] 생성자와 초기화 리스트 (Initializer List)  (0) 2022.05.26
    [C++] 초기화 (Initialization)  (0) 2022.05.25
    [C(++)] Header Guard (헤더 가드) Coding  (0) 2022.02.05
    [C] printf 함수  (0) 2021.12.21
    [C] const type qualifier  (0) 2021.12.21