상세 컨텐츠

본문 제목

C++에서의 구조체

C++/C++98

by deulee 2023. 8. 3. 11:33

본문

사실 구조체는 C에서 나오는 내용하고 그다지 다를바가 없다. 하지만 C++로 넘어오게 되면서 추가된 기능이나 개선점에 집중해서 글을 다뤄보도록 하겠다.

 

우선 구조체는 서로 다른 타입을 가진 변수의 집합이다. 다음의 예시를 통해 보통의 구조체가 어떻게 이용되는지 보도록 하겠다.

 

struct Point
{
	int x;
	int y;
	char ch;
};

구조체를 선언하고 이용되는 과정을 보도록 하자.

#include <iostream>

struct Point {
public: // 이게 기본값임 즉, 굳이 적지 않아도 항상 public으로 선언됨
	int x;
	int y;
	char ch;
};

void printPoint1(const Point& a)
{
	std::cout << a.x << ' ' << a.y << ' ' << a.ch << std::endl;
}

struct Point2 {
public: // 위와 동일함
	int x;
	int y;
	char ch;
	void printPoint2(void)
	{
		std::cout << x << ' ' << y << ' ' << ch << std::endl;
	}
};

int main(void)
{
	Point p1{3, 4, 'c'};
	Point2 p2{5, 6, 'D'};

	printPoint1(p1);
	p2.printPoint2();
	return 0;
}

위의 예제는 구조체 내부를 출력하는 것을 두 가지 방법으로 나타냈다.

 

첫 번재 방법은 구조체와 관련된 함수를 따로 정의한 것이고 두 번째 방법은 구조체에 함수를 포함시켜 정의한 것을 볼 수 있다. 구조체에 포함된 함수를 멤버 함수라고 부르며 구조체에 포함된 변수는 멤버 변수라고 부른다.

 

즉, C++에서 구조체는 멤버 변수와 멤버 함수로 구성되어 있다.

 

위의 예제와 같이 객체 하나로 스스로 동작할 수 있는 독립성이 부여되었다. 멤버 변수로 정보를 기억하고 이 정보들을 바탕으로 직접 동작도 할 수 있다. 이러한 동작성이 생기면 재사용성이 확보된다. 이것이 OOP의 기본적인 개념인 캡슐화이다.

 

멤버 함수 작성법

그럼 어떻게 멤버 함수를 작성하는지 보도록 하자.

 

위에서는 구조체 내부에 직접 함수를 선언 및 정의를 했다. 하지만 멤버 함수가 수백개라면 보기에 매우 안좋을 것이다.

 

이를 위해 외부에 따로 정의할 수 있는데 다음처럼 할 수 있다.

 

struct Point2 {
	int x;
	int y;
	char ch;
	void printPoint2(void);
    inline void printInline(void); // 함수 원형 앞에 inline 키워드를 넣음으로써 인라인 함수로 바꿔줄 수 있다.
};

void Point2::printPoint2(void) // 반환타입 소속구조체::멤버함수(인수)
{
	std::cout << x << ' ' << y << ' ' << ch << std::endl;
}

inline void Point2::printInline(void) // 반환타입 앞에 inline을 명시 함으로써 인라인 함수로 바꿔줄 수 있다.

 

그럼 어떤 차이가 있을까?

 

  • 내부 정의

    인라인 함수의 속성을 가진다. 실제로 함수가 호출되는 것이 아니라 멤버 함수를 호출하는 코드가 함수의 본체 코드로 대체된다.

  • 외부 정의

    일반적인 함수 호출과 마찬가지 방법으로 멤버 함수를 호출한다. 스택을 경유하여 인수를 넘기고 제어의 분기가 발생한다.

 

이게 싫으면 외부 정의를 위의 예제와 같이 바꿔서 inline 함수로 만들어 줄 수 있다.

 

반대로 내부 멤버 함수를 일반 함수처럼 호출하는 방법은 없는데 이 이유는 다음과 같다.

 

클래스 선언은 어디까지나 클래스의 모양을 알리는 것이므로 실제 코드가 생겨나지 않는다. 컴파일러가 선언문만 읽고 마음대로 함수의 본체 코드를 생성할 수는 없는데 만약 이렇게 된다면 헤더 파일에 정의된 클래스 선언문을 읽을 때마다 함수가 중복 생성될 것이다. 컴파일러는 선언문을 기억해 두었다가 함수가 호출될 때 클래스 내부에 선언된 함수 본체 코드를 호출부에 기록할 수밖에 없으며 따라서 내부 정의는 무조건 인라인이다.

 

액세스 지정

구조체의 멤버는 외부에서 언제든지 참조할 수 있다.

 

하지만 C++은 외부에서 내부의 멤버를 함부로 건드리지 못하도록 하는 기능이 있는데 이를 액세스 지정이라고 한다.

 

  • private : 이 속성을 가진 멤버는 외부에서 액세스할 수 없으며 객체 스스로만이 액세스할 수 있다. 외부에서는 존재 자체도 알려지지 않는다.

  • public : 이 속성은 위에서 한번 언급한 속성으로 struct(구조체)의 기본 속성으로 외부로 공개되어 누구나 읽고 쓸 수 있고 함수의 경우는 호출할 수 있다. 구조체가 자신의 속성이나 동작을 외부로 공개하는 수단이 된다. 이러한 퍼블릭 멤버인터페이스라고 한다.

  • protected : private과 마찬가지로 외부에서는 액세스 할 수 없으나, 상속된 파생 클래스는 이 속성을 가진 멤버를 액세스할 수 있다. private 속성을 가진 멤버는 파생 클래스에서조차도 액세스할 수 없다.
struct Foo {
private: // 외부 액세스 x, 파생 클래스 x
	int a;

protect: // 외부 액세스 x, 파생 클래스 o
	int b;

public: // 외부 액세스 o, 파생 클래스 o
	int c;
};

출처

http://www.soen.kr/lecture/ccpp/cpplec.htm

 

C/C++ 강좌

 

www.soen.kr

 

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

C++ 클래스  (0) 2023.08.03
OOP란?  (0) 2023.08.03
new 연산자  (0) 2023.08.03
C++의 새로운 입출력 - cout, endl, cin  (0) 2023.06.10
using 키워드  (0) 2023.06.10

관련글 더보기