【问题标题】:Error C2228 when constructing boost::function object in constructor argument list在构造函数参数列表中构造 boost::function 对象时出现错误 C2228
【发布时间】:2009-06-14 12:13:36
【问题描述】:

以下代码无法在 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);

前面的代码有什么问题?

【问题讨论】:

    标签: c++ visual-c++ templates argument-passing boost-function


    【解决方案1】:

    这是一个函数的函数声明,它引用 boost:function &lt;void()&gt; 并返回 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 中提到的歧义一样,解决方案是将任何可能是声明的构造视为声明。 [注意:声明可以通过非函数式强制转换、= 表示初始化或删除参数名称周围的多余括号来明确消除歧义。 ]

    请注意,为了控制优先级,您可以在任何地方引入括号,如下所示

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

    【讨论】:

      【解决方案2】:

      这被称为“C++ 最令人烦恼的解析”(来自 a book by Scott Meyers called Effective STL)。

      作为answered above,编译器更喜欢将有问题的行解释为函数声明。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-08-18
        • 2021-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多