2009-12-19 4 views
6

mit dem folgenden Code:Copy-Konstruktor nicht genannt, aber Compiler beschwert, dass es keine

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

}; 

Mein Compiler (GCC 4.2) klagt:

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

Ich rufe aber nicht den Kopierkonstruktor !

Antwort

11

Sie rufen nie Kopierkonstruktor auf. Der Kopierkonstruktor wird implizit immer vom Compiler für Sie aufgerufen. Sie müssen lernen, Situationen zu erkennen, in denen es aufgerufen werden könnte.

Wenn Sie fügen Sie eine konstante Referenz auf ein temporäres Objekt

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

die Compiler hat das Recht, eine Kopie des temporären Objekts auszuführen und eine zugängliche Copykonstruktor erfordern (auch wenn es nicht tatsächlich aufgerufen wird,). Dies verursacht das Problem in Ihrem Fall.

Mit anderen Worten, wenn Sie einen Typ nicht kopierbar machen, geben Sie auch die Möglichkeit auf, konstante Referenzen auf temporäre Objekte dieses Typs anzuhängen.

+0

Danke. Ich habe etwas Neues gelernt ... –

1

Zuerst entfernen Sie die private Ableitung von SpecialFilter - es ist nicht notwendig, da der Filter bereits nicht kopierbar ist. Probleme wie diese sind, warum ich Lösungen wie boost :: non_copyable für eine schlechte Idee halte - es gibt einfachere Möglichkeiten zu sagen, dass Sie keine Kopien wollen.

Zweitens, obwohl ich nicht sicher bin, das ist Ihr Problem, C++, sagt, dass eine öffentliche Copykonstruktor an den Compiler unter mehreren circimstances verfügbar sein müssen, auch wenn der Compiler nicht wirklich es verwenden.

0

Denken Sie daran, wenn Sie Objekt übergeben und Objekt nach Wert zurückgeben -> Kopierkonstruktor wird aufgerufen.