簡體   English   中英

在構造函數參數列表中構造boost :: function對象時出現錯誤C2228

[英]Error C2228 when constructing boost::function object in constructor argument list

下面的代碼不能在Visual C ++ 2005中編譯。

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

如果我在SomeClass構造函數的參數周圍加上括號或在參數列表之外構造boost :: function對象,則可以很好地編譯。

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

先前的代碼有什么問題?

這是函數的函數聲明,它引用boost:function <void()>並返回SomeClass 您可以記住以下規則,該規則適用於許多其他此類歧義消除案例。 您可以在C ++標准的8.2節中找到這些情況的描述。

任何可能是聲明的構造都將被視為聲明

這意味着,以下內容將作為帶有多余括號的參數聲明

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

如果刪除括號,這將變得清楚

boost::function<void()> &someFunc

因此,整個聲明將不再聲明一個對象,而是一個函數

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

要修復它,請使用強制轉換符號

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

或者像您一樣在整個表達式上加上括號。

8.2這是所有標准的榮耀:

在6.8的聲明中,也可能發生由函數樣式轉換和6.8中提到的聲明之間的相似性引起的歧義。 在這種情況下,選擇是在帶有圍繞參數名稱的一對多余括號的函數聲明和以函數樣式作為初始值設定項的對象聲明之間進行選擇。 就像6.8中提到的歧義一樣,解決方案是考慮可能是聲明的任何構造。 [注意:聲明可以通過非函數樣式強制轉換,使用=表示初始化或通過刪除參數名稱周圍的多余括號來明確消除歧義。 ]

請注意,為了控制優先級,您幾乎可以在任何地方引入括號,如下所示

int (((((((a))))))) = 3;
int (*(pa)) = &a;

這被稱為“ C ++的最令人煩惱的解析”(摘自Scott Meyers的一本書,稱為“有效STL” )。

如上所述 ,編譯器傾向於將有問題的行解釋為函數聲明。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM