编译错误:使用对象引用的函数参数被构造对象混淆

时间:2010-02-10 22:17:05

标签: c++ reference compiler-errors

在类的单元测试中,我尝试通过显式调用空构造函数来声明一个类变量,并将其传递给一个函数,该函数除了对我声明的类型的接口的引用之外,但编译器会产生错误。当我在没有任何显式构造函数调用的情况下声明它时,函数接受它。

请参阅以下代码:

//classundertest.h
class IController;

class CClassUnderTest
{
public:
    CClassUnderTest() {}
    virtual ~CClassUnderTest() {}

    unsigned int Run(IController & controller);
};

//testclassundertest.h
#include "UnitTest++.h"

#include "classundertest.h"
#include "icontroller.h"

class CTestController : public IController
{
public:
    CTestController() : IController() {}
    virtual ~CTestController() {}

    virtual void Play(unsigned int i) {}
};

struct CClassUnderTestFixture
{
    CClassUnderTest classUnderTest;
};

TEST_FIXTURE(CClassUnderTestFixture, RunTest)
{
    CTestController controllerA;   

    CHECK_EQUAL(classUnderTest.Run(controllerA), 105U);

    CTestController controllerB();   

    CHECK_EQUAL(classUnderTest.Run(controllerB), 105U);
}

编译器认为controllerB是构造函数的引用:

  

错误:没有匹配函数来调用`CClassUnderTest :: Run(CTestController(&)())'   错误:候选者是:unsigned int CClassUnderTest :: Run(IController&)

我很困惑为什么编译器在实例化controllerB时不允许我调用构造函数,特别是当生产代码看起来没问题时呢?

1 个答案:

答案 0 :(得分:6)

这一行:

CTestController controllerB();

是函数的声明,它不带任何内容并返回CTestController。对于默认构造,您必须简单地省略括号。

这与称为“最令人烦恼的解析”的东西有关。考虑:

struct S {};

int main()
{
    S s(S()); // copy construct a default-constructed S ...?
}

这不起作用。这将s声明为一个函数,它接受一个不带任何内容的函数的指针,并返回一个返回S的S.为了解决这个问题,你可以使用一组额外的括号:

struct S {};

int main()
{
    S s((S())); // copy construct a default-constructed S :)
}