2009-06-14 6 views
2

Der folgende Code kompiliert nicht in Visual C++ 2005.Fehler C2228, wenn boost :: function Konstruktion Objekt in Konstruktorargument Liste

class SomeClass { 
public: boost::function<void()> func; 
     SomeClass(boost::function<void()> &func): func(func) { } 
}; 

void someFunc() { 
    std::cout << "someFunc" << std::endl; 
} 

int main() { 
    SomeClass sc(boost::function<void()>(&someFunc)); 
    sc.func(); // error C2228: left of '.func' must have class/struct/union 
    return 0; 
} 

Wenn ich lege Klammern um das Argument für den Konstruktor oder Someclass konstruiert die boost: : Funktionsobjekt außerhalb der Argumentliste kompiliert es gut.

SomeClass sc((boost::function<void()>(&someFunc))); 
    // or 
    boost::function<void()> f(&someFunc); 
    SomeClass sc(f); 

Was ist das Problem mit dem vorherigen Code?

Antwort

1

Es handelt sich um eine Funktionsdeklaration für eine Funktion, die sich auf eine boost:function <void()> bezieht und eine SomeClass zurückgibt. Sie können sich die folgende Regel merken, die sich auf viele andere solche Fälle von Disambiguierung bezieht. Sie finden Beschreibungen dieser Fälle im Abschnitt 8.2 des C++ Standards.

Jedes Konstrukt, das möglicherweise eine Erklärung wird als Erklärung

Das bedeutet, getroffen werden könnte, wird Folgendes als Parameter Erklärung zur Kenntnis genommen werden, mit überflüssigen Klammern

boost::function<void()>(&someFunc) 

Wenn Sie entfernen die Klammern, dies wird klar

Und so wird nicht mehr die ganze Erklärung ein Objekt deklariert, sondern eine Funktion

SomeClass sc(boost::function<void()> &someFunc); 

es zu beheben, die Guss Notation

SomeClass sc((boost::function<void()>)&someFunc); 

Oder Klammern um den gesamten Ausdruck setzen, wie Sie hat getan.

Hier ist der Standard in seiner ganzen Pracht von 8.2:

Die Mehrdeutigkeit von der Ähnlichkeit zwischen einer funktions Casts und einer Erklärung in 6.8 erwähnt entsteht auch im Rahmen einer Erklärung erfolgen kann. In diesem Kontext besteht die Wahl zwischen einer Funktionsdeklaration mit einem redundanten Satz von Klammern um einen Parameternamen und einer Objektdeklaration mit einer Funktionsart als Initialisierer. Genauso wie bei den in 6.8 erwähnten Unklarheiten ist der Beschluss, jedes Konstrukt zu berücksichtigen, das möglicherweise eine Deklaration darstellen könnte. [Anmerkung: Eine Deklaration kann explizit durch eine Nicht-Funktion-artige Umwandlung, durch a = zur Kennzeichnung der Initialisierung oder durch Entfernen der überflüssigen Klammern um den Parameternamen, eindeutig gemacht werden. ]

Beachten Sie, dass Vorrang für die Steuerung, werden Sie Klammern fast überall, wie in der folgenden

int (((((((a))))))) = 3; 
int (*(pa)) = &a; 
einzuführen erlaubt
Verwandte Themen