2009-12-19 40 views
6

Với đoạn mã sau:Sao chép constructor không được gọi, nhưng trình biên dịch phàn nàn rằng không có

#include <boost/noncopyable.hpp> 

enum Error { ERR_OK=0 }; 

struct Filter : private boost::noncopyable 
{ 
    Filter() {} 
    virtual ~Filter() {} 

    virtual int filter(int* data) const = 0; 

}; 

struct SpecialFilter : public Filter, private boost::noncopyable 
{ 
    inline SpecialFilter(unsigned int min, unsigned int max) : min(min), max(max) {} 
    virtual ~SpecialFilter() {} 

    virtual int filter(int* data) const 
    { 
    // ... 
    return ERR_OK; 
    } 

    unsigned int min; 
    unsigned int max; 
}; 

struct AClass 
{ 
    AClass() {} 
    AClass(const AClass& other) {} 
    ~AClass() {} 

    int specialFilter(int channel, int minThreshold, int maxThreshold) 
    { 
    // ... 
    return filter(channel, SpecialFilter(123, 321)); 
    } 

    int filter(int channel, const Filter& filter) 
    { 
    // ... 
    return ERR_OK; 
    } 

}; 

trình biên dịch của tôi (GCC 4.2) than phiền:

- warning: direct base ‘boost::noncopyable_::noncopyable’ inaccessible in ‘SpecialFilter’ due to ambiguity 
- noncopyable.hpp: In copy constructor ‘Filter::Filter(const Filter&)’: 
- noncopyable.hpp:27: error: ‘boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)’ is private 
- synthezised method first required here: [return filter(channel, SpecialFilter(123, 321));] 

Nhưng tôi không gọi constructor sao chép !

Trả lời

11

Bạn không bao giờ gọi hàm tạo bản sao. Các nhà xây dựng bản sao luôn luôn được gọi cho bạn ngầm bởi trình biên dịch. Vì vậy, bạn cần phải tìm hiểu để nhận ra các tình huống khi nó có thể được gọi.

Khi bạn đính kèm một tham chiếu const đến một đối tượng tạm thời

... 
return filter(channel, SpecialFilter(123, 321)); 
... 

trình biên dịch có quyền thực hiện một bản sao của đối tượng tạm thời và đòi hỏi một constructor sao chép truy cập (ngay cả khi nó sẽ không được thực sự được gọi là). Đây là những gì gây ra vấn đề trong trường hợp của bạn.

Nói cách khác, khi bạn thực hiện một số loại không thể sao chép, bạn cũng từ bỏ khả năng đính kèm tham chiếu const vào đối tượng tạm thời thuộc loại đó.

+0

Cảm ơn. Tôi đã học được điều mới ... –

1

Trước tiên, xóa nguồn gốc riêng khỏi SpecialFilter - không cần thiết vì Bộ lọc không thể sao chép được. Vấn đề như thế này là lý do tại sao tôi nghĩ rằng các giải pháp như boost :: non_copyable là một ý tưởng tồi - có những cách đơn giản hơn để nói rằng bạn không muốn sao chép. Thứ hai, mặc dù tôi không chắc chắn đây là vấn đề của bạn, C++ nói rằng một nhà xây dựng bản sao công khai phải có sẵn cho trình biên dịch theo một số chu kỳ, ngay cả khi trình biên dịch không thực sự sử dụng nó.

0

Hãy nhớ khi bạn vượt qua đối tượng và trả về đối tượng theo giá trị -> hàm tạo bản sao được gọi.

Các vấn đề liên quan