프로그램을 하다보면 어떤 클래스는 절대로 복사되지 말아야하는 경우가 생깁니다. 

 

방법은?

 

우선 복사 생성자와 복사 대입 연산자 자체를 선언하지 않는 방법을 제일 먼저 떠올릴 것이다. 

하지만 컴파일러는 우리가 복사생성자나 복사대입연산자를 선언하지 않으면 자동으로 선언해준다. 

그렇다고 직접 선언하면 복사하는 것은 마찬가지 입니다.

 

해결의 열쇠는 다음과 같습니다.

 

복사 생성자와 복사 대입 연산자를 private 멤버로 선언해버리면, 외부에서 호출할 수가 없으므로 어느정도 효과를 볼 수 있습니다.

그러나! 그 클래스의 멤버 함수, 혹은 friend 함수가 호출할 수 있으므로 이들까지 막아야 합니다.

그럼 아예 정의 자체를 하지 않는 방법이 있습니다. 실제로 이러한 방법은 iostream 라이브러리의 몇몇 클래스에서도 사용되고 있다고 합니다. 

 

ex ) 복사생성자와 복사 대입 연산자를 private에 선언 및 정의 하지 않음

class HomeForSale 

   private
     HomeForSale( const HomeForSale& );  // 매개변수 이름은 필요없다. 사용 안하므로
     HomeForSale& operator=(const HomeForSale& ); 

  public:
     HomeForSale(){}
};

 

HomeForSale h1;

HomeForSale h2;

HomeForSale h3(h1);  // 컴파일 Error, 복사생성자가 public이면 LINK에러 (정의가 없으므로)

h1 = h2;                    // 컴파일 Error  

 

위와같이 private으로 오직 선언만 해주게 되면, 멤버함수나 friend 함수가 접근하다가 LINK 에러를 볼겁니다. 따라서 호출 자체를 막아 버릴 수 있게 되는 것입니다. 

  

또하나, 

위에서 friend함수나 멤버함수가 접근하면 링크에러를 발생하는데, 이 링크에러를 컴파일 에러로 옮기는 방법도 있습니다.

 

방법은?

복사생성자와 복사 대입 연산자를 private 멤버로 선언을 하되, 자체 클래스가 아닌 상위 클래스에서 상속받는 방법을 쓰는 것이다.

 

ex ) 복사를 막는 상위 클래스 제작 

class Uncopyable 

   private
       Uncopyable( const Uncopyable& );
       Uncopyable& operator=( const Uncopyable& );    
   protected
       Uncopyable() {} 
       ~Uncopyable() {} 
 };   
class HomeForSale : private Uncopyable // private 상속 
{
}; 

Uncopyable이라는 클래스를 만들어 private멤버로 복사 생성자와 복사 대입 연산자의 선언만 해준다.

그리고 복사되면 안되는 클래스는 Uncopyable 클래스를 private 상속을 받아 사용하면 된다.

private 상속은 부모 클래스의 protected, public 멤버도 private처럼 바꿔서 상속하기 때문에 자식 클래스에서 부모 클래스의 어떠한 것도 접근할 수 없게 되어버립니다.

 

참고 합시다

Boost 라이브러리에 noncopyable 복사 방지 클래스

 

 

이것 만은 잊지 말자!

◆ 컴파일러에서 자동으로 제공하는 기능을 허용치 않으려면, 대응되는 멤버 함수를 private로 선언한 후에 구현은 하지 않은 채로 두십시오. Uncopyable과 비슷한 기본 클래스를 쓰는 것도 한 방법입니다.


+ Recent posts