2017-12-16 29 views
2

C++을 처음 사용하고 코드가 어떻게되는지 정확하게 이해하려고합니다.빈 생성자를 사용하지 않고 컴파일이 실패합니다.

이 클래스들은 모두 자체 헤더 파일에 정의되어 있습니다. 코드는 다음과 같습니다.

대기열 :

template<class T> class Queue 
{ 
    public: 
    Queue(unsigned int size) 
    { 
     _buffer = new T[size]; //need to make sure size is a power of 2 
     _write = 0; 
     _read = 0; 
     _capacity = size; 
    } 

    /* other members ... */ 

    private: 
    unsigned int _capacity; 
    unsigned int _read; 
    unsigned int _write; 
    T *_buffer; 
}; 

직렬 :

template<class T> class Queue; 
template<class T> class Serial 
{ 
    public: 
    Serial(unsigned int buffer_size) 
    { 
     _queue = Queue<T>(buffer_size); //<---here is the problem 
    } 
    private: 
    Queue<T> _queue; 
}; 

이 같은 일련의 인스턴스를 만들려고 :

Serial<unsigned char> s = Serial<unsigned char>(123); 

컴파일러는 더 큐 생성자가 없음을 불평 제로 논쟁으로, 적어도 그것은 내가 오류라고 생각하는 것입니다 :

In instantiation of 'Serial<T>::Serial(unsigned int) [with T = unsigned char]': 

no matching function for call to 'Queue<unsigned char>::Queue()' 

ambiguous overload for 'operator=' in '((Serial<unsigned char>*)this)->Serial<unsigned char>::_queue = (operator new(16u), (((Queue<unsigned char>*)<anonymous>)->Queue<T>::Queue<unsigned char>(buffer_size), ((Queue<unsigned char>*)<anonymous>)))' (operand types are 'Queue<unsigned char>' and 'Queue<unsigned char>*') 

invalid user-defined conversion from 'Queue<unsigned char>*' to 'const Queue<unsigned char>&' [-fpermissive] 

invalid user-defined conversion from 'Queue<unsigned char>*' to 'Queue<unsigned char>&&' [-fpermissive] 

conversion to non-const reference type 'class Queue<unsigned char>&&' from rvalue of type 'Queue<unsigned char>' [-fpermissive] 

나는 그것이 아무런 문제없이 컴파일 큐에 빈 생성자를 추가 할 때. 디버거를 단계별로 실행할 때 빈 매개 변수가 아닌 매개 변수를 사용하여 생성자로 들어갑니다.

왜 이런 일이 발생합니까?

+0

언어는 기능 클래스를 자동으로 생성 얻을 무엇과 관련된 규칙을 많이했다. 인수를 사용하여 생성자를 정의하면 컴파일러에서 만들어지는 함수를 수정합니다. 귀하의 경우, 인수를 사용하여 생성자를 정의 했으므로 기본 (빈) 생성자를 얻지 못했습니다. 코드에 기본값이 필요합니다 (게시 된 답변 참조). – ttemple

+1

[this one] (https://www.ideone.com/OOdq5n)과 같이 [mcve]를 만들어야합니다. 이 문제는 템플릿, 대기열, 헤더 파일 등과는 아무런 관련이 없습니다. – PaulMcKenzie

+1

https://stackoverflow.com/questions/4782757/rule-of-three-becomes-rule-of-five-with-c11#4782927 생성자를 만들 때 일반적으로 다른 함수 (복사 생성자, 할당 등)와 그 이유를 만들어야합니다. 제안 된 3 또는 5 중 하나만 만들었습니다. – ttemple

답변

5

Serial(unsigned int buffer_size)_queue는 먼저 기본 생성자로 만들 수 있고, 그 다음 값 (Queue<T>(buffer_size))이 할당되고, 따라서 member init list 없다.

이 :

Serial(unsigned int buffer_size) : _queue(buffer_size) {} 

대신 Queue(unsigned int) 생성자를 사용하는 것이 기본 생성자없이 작업 한 것입니다.

+0

설명 주셔서 감사합니다. 나는 Serial (unsigned int buffer_size)을 사용해야했다 : _queue (buffer_size) 컴파일을 위해 (괄호는 없다) – Marius

+2

@Marius :'{}'는 생성자 본문이다. 너 하나 필요해, 근데 네가 두 명 있니? –

1

OPS 클래스보고 포인터의 배열 개인적으로 나는이 유사한 방식으로 클래스를 설계하는 것 ctor에 새로운 사용의 사용보고 :

#ifndef QUEUE_H 
#define QUEUE_H 

template<class T> 
class Queue { 
private: 
    size_t size_; 
    size_t capacity_; 
    size_t read_; 
    size_t write_; 

    // Either of these depending on case of use or ownership 
    std::vector<std::shared_ptr<T>> buffer_; 
    std::vector<std::unique_ptr<T>> buffer_; 
public: 
    Queue() {} 

    explicit Queue(size_t size) : size_(size) { 
     buffer_.resize(size_); 
    } 
}; // Queue 

#endif // !QUEUE_H 

직렬

#ifndef SERIAL_H 
#define SERIAL_H 

template<class T> class Queue; 

template<class T> 
class Serial { 
private: 
    Queue<T> queue_; 

public: 
    Serial() {} 
    explicit Serial(size_t bufferSize) { 
     queue_ = Queue<T>(bufferSize); 
    } 
}; // Serial 

#endif // !SERIAL_H 

시리얼 클래스는 많은 아닙니다 큐 유형의 스택 개체를 사용하고 있기 때문에 문제가 발생했습니다. 이제 Queue 객체는 new operator과 함께 포인터를 사용하기 때문에 소멸자가 일종의 메모리 리소스를 관리해야한다는 것을 직접 나타내는 delete operator과 일치해야합니다.

array[size] raw pointers 대신 vector<smart_ptr>을 사용하기로 결정했습니다. 이것은 메모리 누수, 매달려있는 포인터 등을 막는 데 도움이됩니다.Rule of 3 완료하는 데이 3 적어도 쓰는 것이 중요하다 :

  • Destructor
  • Copy Constructor
  • Assignment Operator

을 그리고 이것들이 Rule of 5을 완료하기 위해 작성해야 할 수도 있습니다 :

  • Move Constructor
  • Move Assignment Operator