2

我在 Visual Studio 2005 中有以下 C++ 代码...

class Base {};
class Derived : public Base {};

class Other {
public:
 Other(const Base& obj) {}
 void test() {}
};

int _tmain(int argc, _TCHAR* argv[])
{
 Other other(Derived());
 other.test();
 return 0;
}

...编译失败并给出:

test.cpp(19) : error C2228: left of '.test' must have class/struct/union

我通过一些测试确定会发生这种情况,因为“other”变量的声明被解释为函数声明(返回 Other 并采用 Derived 参数),而不是使用单参数构造函数的 Other 的实例。(VS6 找到构造函数并编译它很好,但它不擅长标准 C++ 所以与 VS2005 相比我不信任它)

如果我做...

Other other(static_cast<Base&>(Derived()));

...或使用复制初始化,它工作正常。但是似乎没有看到 Derived() 实例是从 Base 派生的,或者它优先考虑函数声明而不是尝试在构造函数参数上进行多态性。

我的问题是:这是标准的 C++ 行为,还是 VS2005 特有的行为?应该...

Other other(Derived());

...在标准 C++ 中声明一个本地实例,还是应该声明一个函数?

4

3 回答 3

3

是的,这是标准行为。请参阅此 C++ FAQ-lite 条目

根据标准,这是:

Other other(Derived());

被解释为一个函数声明,该函数返回 Other 并将另一个返回 Derived 且没有参数的函数作为参数。要解决此问题,您可以使用:

Other other = Other(Derived());
于 2010-02-04T00:10:27.540 回答
2

您在问题的标题中提到了“多态参数”,而实际上所有这些都与任何多态参数无关。在 C++ 中,有问题的声明声明了一个函数,而不管您提供的“参数”是否是多态的。

像往常一样,您可以使用额外的一对()来解决此问题

Other other((Derived())); // now it is an object, not a function

您还可以使用任何其他方法将Derived()零件转换为表达式,例如

Other other((const Derived&) Derived()); 

或者

Other other(((void) 0, Derived())); 
于 2010-02-04T00:20:43.163 回答
1

我在 VS2008 和 GCC 中尝试了你的示例,它也发生在那里。

看起来,该语法实际上是通过以下声明将 other 声明为函数指针:

Other other(Derived (*)(void))

正确的行为应该是使用初始化:

Other other = Derived();
于 2010-02-04T00:13:04.093 回答