2017-05-17 1 views
3

컴파일러 오류가 아닌 순수 추상 인터페이스에 대한 참조 해제 포인터에서 대입 연산자를 사용하는 이유는 무엇입니까? 언제 이것이 유용 할 수 있습니까? 내가 아래에서 개괄 한 것처럼 미묘한 버그로 이어질 수있는 것처럼 보입니다.역 참조 포인터에서 대입 연산자를 사용하여 컴파일러 오류가 아닌 인터페이스를 사용하는 이유는 무엇입니까?

나중에 구현할 수있는 인터페이스를 구현하는 전역 적으로 액세스 가능한 객체를 갖기 위해 핸들 (포인터에 대한 포인터 또는 std에 대한 포인터 사용)을 사용해야합니까? :: unique_ptr) 아니면 다른 접근 방법이 있습니까?

#include <iostream> 

class Interface { 
public: 
    virtual int Value() = 0; 
}; 

class Implementation : public Interface { 
public: 
    Implementation(int value) : value(value) {} 
    int Value() override { 
    return value; 
    } 
    int value; 
}; 

// Set default value 
Interface* object = new Implementation(1); 
Implementation* object2 = new Implementation(2); 

int main() { 
    // Why is this line not a compiler error? 
    *object = Implementation(3); // Try to override default value 
    *object2 = Implementation(4); // Override default value 
    // This outputs "14", not "34", why? 
    std::cout << object->Value() << object2->Value(); 
    return 0; 
} 

이러한 문제를 해결하고 단위 테스트에서 재정의 기본값을 설정할 수있게하려면 다음 방법을 사용했습니다. 기본적으로

// Set default value 
static std::unique_ptr<Interface> object(new Implementation(1)); 
void SetObject(std::unique_ptr<Interface> obj) { 
    object.reset(obj.release()); 
} 

int main() { 
    SetObject(std::make_unique<Implementation>(2)); // Override default value 
    std::cout << object->Value(); 
    return 0; 
} 

답변

5

C++ 객체는 컴파일러에 의해 생성 된 operator= 방법을 얻을. 이 연산자는 각각의 멤버 변수에 operator=을 적용하고 이 아니고 가상입니다. 즉, 정적 유형의 선언 된 포인터의 멤버와 함께 작동합니다. Interface에는 회원이 없으므로 구성원이 복사되지 않습니다. Implementation에는 회원이 있으므로 회원이 복사됩니다.

+0

나는 본다. 그래서 진짜 문제는 "인터페이스"가 "순수한 추상 인터페이스"라는 나의 주장이었습니다. 실제로는 그렇지 않습니다. 그 경우를 위해서, 필자는 기대했던 컴파일러 오류가 있기 위해 기본 함수를 삭제하는 것과 같은 몇 가지 사항을 추가해야 할 것입니다. "인터페이스 & 연산자 = (const 인터페이스 &) = 삭제;" – AffluentOwl

+0

@AffluentOwl이 정확합니다. –

+0

가상 인터페이스에서 대입 연산자를 만드는 방법이 있습니까? 그리고이 함수를 "34"가 될 주 함수의 최종 출력을 얻을 수있는 방법으로 재정의 할 수 있습니까? – AffluentOwl

관련 문제