(전체가 아니라 C#과 차이가 있는 부분을 중심으로 요약 정리)

friend

C++는 클래스 안에서 다른 클래스나 다른 클래스의 멤버 함수 또는 비멤버 함수를 friend로 선언하는 기능을 제공한다. friend로 지정한 대상은 이 클래스의 protected나 private 데이터 멤버와 메서드에 접근할 수 있다. (이런 거를 왜 만들어 놨지? 이런거는 설계가 너무 난잡해진다. 상속이나 interface, component를 이용할 것)

예컨대 Foo와 Bar라는 두 클래스가 있다고 하자. 그리고 다음과 같이 Bar 클래스를 Foo의 프렌드로 지정한다.

class Foo
{
  friend class Bar;
  // ...
}

이렇게 하면 Bar에 있는 모든 메서드는 Foo의 private이나 protected 데이터 멤버 및 메서드에 접근할 수 있다.

Bar에 있는 메서드 중 특정한 메서드만 프렌드로 만들기 원할 수 있다. 그럴 때는 다음과 같이 작성한다.

class Foo
{
  friend void Bar::processFoo(const Foo& foo);
  // ...
}

스탠드언론 함수도 클래스의 프렌드가 될 수 있다. 예컨대 Foo 객체에 있는 데이터를 콘솔에 출력하는 함수를 만든다고 하자. 이 함수를 Foo 클래스 밖에서 검사하는 모델로 만들려고 하는데, 제대로 검사하라면 이 객체의 내부 데이터 멤버의 값에 접근해야 한다. 이때 Foo 클래스 정의에 다음과 같이 dumpFoo() 함수를 프렌드로 만들면 된다.

class Foo
{
  friend void dumpFoo(const Foo& foo);
  // ...
}

이 클래스에서 friend 선언문은 함수 프로토타입의 역할을 한다. 이렇게 지정한 프로토타입은 다른 곳에 따로 선언하지 않아도 된다. (물론 그렇게 해도 문제가 발생하지는 않는다)

이 함수의 정의는 다음과 같다.

void dumpFoo(const Foo& foo)
{
  // private 및 protected 데이터 멤버를 비롯한 foo의 데이터를 모두 콘솔에 출력한다.
}

이 함수를 작성하는 방법은 다른 함수와 같다. Foo의 private와 protected 데이터 멤버에 직접 접근할 수 있다는 점만 다르다. 이렇게 함수를 정의할 때는 friend 키워드를 생략해도 된다.

프렌드로 지정할 클래스, 메서드, 함수는 반드시 접근할 클래스 안에서 지정해야 한다. 이들을 다른 곳에서 대상 클래스의 프렌드라고 선언해서 그 클래스의 private이나 protected 멤버에 접근하게 할 수는 없다.

클래스마 네서드를 프렌드로 지정하는 기능을 너무 많이 사용하면 클래스의 내부가 외부 클래스나 함수에서 드러나서 캡슐화 원칙이 깨진다. 따라서 꼭 필요할 때만 사용한다.

객체에 동적 메모리 할당하기

Spreadsheet 클래스

8장에서 SpreadsheetCell 클래스를 다루었는데 여기서는 Spreadsheet 클래스를 작성해보겠다. 먼저 Spreadsheet를 SpreadsheetCell 타입의 2차원 배열로 만든다. 그리고 Spreadsheet에서 특정 위치에 있는 셀을 설정하거나 조회하는 메서드를 정의한다. 상용 스프레드시트 애플리케이션은 한 축은 문자, 다른 축은 숫자를 사용하지만 여기서는 모두 숫자로 표시한다.

Spreadsheet의 첫 버전은 다음과 같다.