2009-12-19 2 views
6

Учитывая следующий код:конструктор копирования не вызывается, но компилятор жалуется, что нет

#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; 
    } 

}; 

Мой компилятор (GCC 4.2) жалуется:

- 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));] 

Но я не называю конструктор копирования !

ответ

11

Вы никогда не вызываете конструктор копирования. Конструктор копирования всегда вызывается неявным образом компилятором. Поэтому вам нужно научиться распознавать ситуации, когда это может быть вызвано.

При подключении константной ссылки на временный объект

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

компилятор имеет право выполнять копию временного объекта и требуется доступный конструктор копирования (даже если он не будет на самом деле называется). Это то, что вызывает проблему в вашем случае.

Другими словами, когда вы делаете какой-либо тип, не подлежащий копированию, вы также отказываетесь от возможности привязывать ссылки const к временным объектам этого типа.

+0

Спасибо. Я узнал что-то новое ... –

1

Во-первых, удалите частный вывод из SpecialFilter - это необязательно, так как фильтр уже не может быть скопирован. Такие проблемы, почему я думаю, что такие решения, как boost :: non_copyable, являются плохой идеей - есть более простые способы сказать, что вы не хотите копировать.

Во-вторых, хотя я не уверен, что это ваша проблема, C++ говорит, что открытый компилятор должен быть доступен компилятору в нескольких циклах, , даже если компилятор фактически не использует его.

0

Помните, когда вы передаете объект и возвращаете объект по значению -> вызывает конструктор копирования.