C++ Rule of Three에 대해 많이 읽었습니다. 많은 사람들이 그것을 맹세합니다. 그러나 규칙이 명시 될 때 예외가 있음을 나타내는 "보통", "가능성 있음"또는 "아마도"와 같은 단어가 거의 항상 포함됩니다. 나는이 예외적 인 경우가 무엇인지에 대한 많은 논의를 보지 못했다. 3 가지 규칙이 성립하지 않는 경우 또는 적어도 그 규칙을 준수하는 것이 이점을 제공하지 않는 경우이다.3의 규칙에 대한 예외?
제 질문은 제 상황이 제 3 규칙의 정당한 예외인지 여부입니다. 필자는 아래에서 설명한 상황에서 명시 적으로 정의 된 복사 생성자와 복사 할당 연산자가 필요하다고 생각하지만 기본 (암시 적으로 생성 된) 소멸자는 정상적으로 작동합니다. 여기에 내 상황이있다 :
두 개의 클래스 A와 B가있다. 여기에있는 질문은 A. B는 A의 친구이다. A에는 B 개체가 들어있다. B는 B 오브젝트를 소유하는 A 오브젝트를 가리 키기위한 A 포인터를 포함합니다. B는이 포인터를 사용하여 A 객체의 전용 멤버를 조작합니다. B는 A 생성자를 제외하고 결코 인스턴스화되지 않습니다. 이처럼 :
// A.h
#include "B.h"
class A
{
private:
B b;
int x;
public:
friend class B;
A(int i = 0)
: b(this) {
x = i;
};
};
그리고 ... 내가 그렇게 내 클래스를 설정하는 것이 왜
// B.h
#ifndef B_H // preprocessor escape to avoid infinite #include loop
#define B_H
class A; // forward declaration
class B
{
private:
A * ap;
int y;
public:
B(A * a_ptr = 0) {
ap = a_ptr;
y = 1;
};
void init(A * a_ptr) {
ap = a_ptr;
};
void f();
// this method has to be defined below
// because members of A can't be accessed here
};
#include "A.h"
void B::f() {
ap->x += y;
y++;
}
#endif
? 나는 좋은 이유가 있다고 약속한다. 이 클래스는 실제로 여기에 포함 된 것보다 더 많은 일을합니다.
나머지는 쉽습니다. 그렇죠? 자원 관리가 없으며 Big Three도 문제가 없습니다. 잘못된! A에 대한 디폴트 (내재적) 복사 생성자는 충분하지 않습니다. 우리는이 작업을 수행 할 경우
A a1;
A a2(a1);
우리는 새로운
a2.b.ap
의미
a2.b
이
a1.b
동일 의미
a1
동일 인 객체
a2
는 여전히
a1
가리키는 얻을! 이것은 우리가 원하는 것이 아닙니다. A에 대한 복사 생성자를 정의해야합니다.이 복사 생성자는 기본 복사 생성자의 기능을 복제 한 다음 새 A 객체를 가리 키도록 새
A::b.ap
을 설정합니다. 우리는
class A
이 코드를 추가
public:
A(const A & other)
{
// first we duplicate the functionality of a default copy constructor
x = other.x;
b = other.b;
// b.y has been copied over correctly
// b.ap has been copied over and therefore points to 'other'
b.init(this); // this extra step is necessary
};
복사본 할당 연산자는 같은 이유로 필요하며, 기본 복사 할당 연산자의 기능을 복제 한 후 b.init(this);
를 호출하는 동일한 프로세스를 사용하여 구현된다.
그러나 명시 적 소멸자가 필요하지 않습니다. 이 상황은 규칙 3에 대한 예외입니다. 내가 맞습니까?
우리는 이러한 유형의 질문이 더 필요합니다. – Shoe
대문자가 뒤 따르는 모든 밑줄이 시스템 용으로 예약되어 있으므로 포함 보호 _B는 불법입니다. – metal
C++ 11의 경우, 제로 규칙이 더 좋습니다 : http://flamingdangerzone.com/cxx11/2012/08/15/rule-of-zero.html이 경우 A와 B의 수명을 관리 할 수 있습니다. B std :: unique_ptr, std :: shared_ptr 및 여기에 std :: weak_ptr (또는 유사한 소유 클래스)를 사용합니다. 6 개월 후에 당신의 코드 독자들에게 그 모든 수수께끼를 풀어줍니다. – metal