2009-12-19 16 views
6

Dado el siguiente código:constructor de copia no se llama, pero el compilador se queja de que no hay

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

}; 

Mi compilador (GCC 4.2) se queja:

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

Pero yo no llame al constructor de copia !

Respuesta

11

Nunca llama al constructor de copias. El compilador siempre llama al constructor de copia para usted implícitamente. Por lo tanto, debe aprender a reconocer situaciones en las que se podría llamar.

Al adjuntar una referencia constante a un objeto temporal

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

el compilador tiene derecho a realizar una copia del objeto temporal y requieren un constructor de copia accesible (incluso si no se llama en realidad) Esto es lo que está causando el problema en tu caso.

En otras palabras, cuando hace que un tipo no se pueda copiar, también abandona la posibilidad de adjuntar referencias de referencias a objetos temporales de ese tipo.

+0

Gracias. Aprendí algo nuevo ... –

1

En primer lugar, elimine la derivación privada de SpecialFilter; no es necesario, ya que el filtro ya no se puede copiar. Problemas como este son los motivos por los que creo que las soluciones como boost :: non_copyable son una mala idea: hay formas más simples de decir que no quieres copias.

En segundo lugar, aunque no estoy seguro de que este es su problema, C++ dice que una copia constructor público debe estar disponible para el compilador bajo varios circimstances, incluso si el compilador no utiliza realmente se.

0

Recuerde cuando pasa el objeto y devuelve el objeto por valor -> se invoca el constructor de copia.

Cuestiones relacionadas