2014-05-13 12 views
1

템플릿 클래스 C가 있습니다. 다른 클래스의 크기에 따라 데이터 배열의 크기를 조정하는 템플릿 복사 생성자가 필요합니다.기본 복사 생성자를 템플릿 복사 생성자로 바꿉니다.

다음은 간단한 예입니다. 그것은 잘 작동합니다. 그러나 Constructor 2Constructor 3이 매우 유사하다는 것을 알아 두십시오. 하나로서 병합 할 수 있는지 궁금합니다.

또한 Constructor 3을 간단히 제거하면 C<int> c3(c1)Constructor 2을 호출하지 않고 컴파일러에서 추가 한 기본 복사 생성자를 호출합니다. 이로 인해 메모리가 제대로 할당되지 않습니다. 위의 함수의

template<typename T> 
class C 
{ 
public: 
    T* val; 
    int size; 
public: 

    C(int s = 0) { 
     cout << "Constructor 1" << endl; 
     size = s; 
     val = (size) ? new T[size] : nullptr; 
    } 

    template<class T2> 
    C(const C<T2>& c2) { 
     cout << "Constructor 2" << endl; 
     size = c2.size; 
     val = (size) ? new T[size] : nullptr; 
    } 

    C(const C<T>& c2) { 
     cout << "Constructor 3" << endl; 
     size = c2.size; 
     val = (size) ? new T[size] : nullptr; 
    } 

    ~C() { 
     cout << "~C()" << endl; 
     delete[] val; 
     val = nullptr; 
    } 
}; 

int main(void) 
{ 
    C<int> c1(5); 
    C<float> c2(c1); 
    C<int> c3(c1); 

    return 0; 
} 

출력 :

Constructor 1 
Constructor 2 
Constructor 3 
~C() 
~C() 
~C() 
+1

C++ 11에서 생성자 위임을 사용하거나이 초기화를 수행하는 멤버 함수 (도우미)를 사용할 수 있습니다. – dyp

+0

할당하고있는 메모리에 유용한 것을 만들고 싶다면, 소스 타입의 객체로 할 생성자 2는 무엇인가? – Praetorian

+0

당신은 그 생성자에서'c2.val'의 원소의 복사본을 수행하려고합니까? – dyp

답변

1

template<class T2> 
C(const C<T2>& c2, int dummy) { 
    cout << "Constructor 2" << endl; 
    size = c2.size; 
    val = (size) ? new T[size] : nullptr; 
} 

template<class T2> 
C(const C<T2>& c2) : C(c2, 0) {} 

C(const C<T>& c2) : C(c2, 0) {} 

업데이트로

template<class T2> 
C(const C<T2>& c2) { 
    cout << "Constructor 2" << endl; 
    size = c2.size; 
    val = (size) ? new T[size] : nullptr; 
} 

C(const C<T>& c2) { 
    cout << "Constructor 3" << endl; 
    size = c2.size; 
    val = (size) ? new T[size] : nullptr; 
} 

를 교체

당신은 사용할 수 :

C(int s = 0) { 
    cout << "Constructor 1" << endl; 
    size = s; 
    val = (size) ? new T[size] : nullptr; 
} 

template<class T2> 
C(const C<T2>& c2) : C(c2.size) {} 

C(const C<T>& c2) : C(c2.size) {} 

두 번째 생성자가 필요하지 않습니다.

+0

너무 우아하지 않습니다. 그러나 이것이이 문제를 해결할 수있는 유일한 방법 인 것 같습니다. –

+0

@YuchenZhong 내 업데이트를 참조하십시오. –

+0

일반적으로 특수 개인 클래스를 더미 유형으로 사용하고 해당 개인을 비공개로 만듭니다. 이렇게하면 과부하 문제 (부주의로 해당 ctor를 호출하는 클래스의 사용자)를 방지 할 수 있습니다. – dyp

0

하나는 C++ (11) 위임 생성자와이를 구현하고 싶습니다. 그러나 템플릿 매개 변수가 클래스 또는 생성자에 있는지 여부가 모호하므로이 방법이 직접적으로 불가능합니다. 이 문제를 해결하기 위해 공통 코드를 도우미 함수로 분해 할 수 있습니다.

무엇인가 :

template<class T2> 
    C(const C<T2>& c2) { 
     Copy<T2>(c2); 
    } 

    C(const C<T>& c2) { 
     Copy<T>(c2); 
    } 

private: 
    template<class T2> 
    void Copy(const C<T2>& c2) { 
     cout << "Constructor 2" << endl; 
     size = c2.size; 
     val = (size) ? new T[size] : nullptr; 
    } 
+1

두 번째 생성자가 자신에게 위임 중인지 확실히 확인하십시오. 편집 : [그래, 그거야] (http://coliru.stacked-crooked.com/a/c052b789d02eddef). 재미있는 것은 clang이이를 감지하고 오류를 던지는 반면 gcc는 segfaults입니다. – Praetorian

+0

@Praetorian : 맞습니다. 나는 일반적인 아이디어를 얻으려고 노력했다. 하지만 그렇습니다. 원하는대로 템플릿 매개 변수가 해결되지 않습니다. btw, VS에서는 경고를 오류로 취급하지 않는 한 "성공"건물을 얻습니다. 나는 두 번째 ctor의 서명을 변경하지 않는 약간 다른 것으로 대답을 업데이트했습니다. – Apriori

관련 문제