【问题标题】:Why does this class object declaration work?为什么这个类对象声明有效?
【发布时间】:2018-10-04 04:47:11
【问题描述】:

假设我有一堂课

class Test{
  public:
    int x;
    Test(const Test& obj){x=obj.x;}
};

为什么

Test object_name(Test random_name);

运行并且不需要另一个对象作为参数?。 . 像Test random_name(Test another_random(...)) 这样的东西,让它成为一种永无止境的对象声明方式?

【问题讨论】:

  • Test object_name(Test random_name); 是一个函数声明,它不会“运行”。
  • OP 是对的,它compiles and runs on g++,即使是Test object_name(Test random_name (Test another_random_name (Test new_identifier)));
  • 这不是错误。这是一个有效的函数声明。它没有任何问题。
  • 不是对象创建,你在int main()函数中声明了一个函数
  • 我同意 P.W.这看起来像是经常出现的“最令人头疼的解析”类型问题的变体……

标签: c++ oop


【解决方案1】:

这一行:

Test object_name(Test random_name);

声明一个名为object_name 的函数,它接受Test 作为参数并返回Test。它不声明对象。在另一个函数中声明这样的函数是完全合法的,它只是隐含的extern

【讨论】:

  • 我的主函数看起来像 int main() { Test Object_name(Test random_name);返回0;我想问,为什么这不是错误?括号中的对象理想情况下应该需要另一个对象,并且应该继续。
  • 另请注意:编译器可以接受声明,但任何使用object_name 的尝试都会使这一事实变得明显。示例错误:“main.cpp:15:25: error: request for member ‘x’ in ‘object_name’, which is non-class type ‘Test(Test)’”。
  • @ViditVirmani:这里没有对象——只是一个从未调用过的函数的外部函数声明。如果你试图调用它,你会得到一个链接错误,但正如你所描述的,没有错误。
  • @ViditVirmani 你在int main()函数中声明一个函数
【解决方案2】:

Test 替换为int 之类的PoD,您将看到发生了什么

Test object_name(Test random_name); //1

int object_name(int random_name); //2

您可以看到第二条语句是一个函数声明,它以int 作为参数并返回一个int

这是由于 CPP 中与歧义解决相关的众所周知的规则。
来自 CPP 工作草案 (N4713):

9.8 歧义分辨率 [stmt.ambig]

1 在涉及表达式语句和声明的语法中存在歧义:将函数样式显式类型转换作为其最左边的子表达式的表达式语句与第一个声明符以 a 开头的声明无法区分(。 在这些情况下,声明就是声明

2 [注:如果语句在语法上不能是声明,则没有歧义,因此该规则不适用。可能需要检查整个语句以确定是否是这种情况。

【讨论】:

  • 我很喜欢这个答案。它非常清楚地表明了一个人的误解可能在哪里。
【解决方案3】:

这是一个重构版本,应该有助于解释发生了什么。我添加了另一个构造函数来说明发生了什么。

#include <iostream>

using namespace std;

class Test{
  public:
    int x = 27;
    Test(const int y) : x(y) { cout << "ctor-1" << endl; }
    ~Test() {}
    Test(const Test& obj) : x(obj.x) { cout << "ctor-2" << endl; }
    operator int() const { return x; }
};

int main()
{
    cout << "Creating function declaration" << endl;
    Test object_name(Test random_name);

    // This works fine
    cout << "Creating alpha" << endl;
    Test alpha(4);
    cout << "Calling `object_name`" << endl;
    cout << object_name(alpha) << endl;

    // This fails because object_name is a function.
    // cout << object_name.x << endl;
    return 0;
}

Test object_name(Test random_name)
{
    cout << "Creating another Test within `object_name`." << endl;
    return Test(random_name.x + 13);
}

在这里,我们看到第一个构造函数被调用了两次:一次用于alpha,另一次用于object_name。第二个构造函数在我们调用object_name时被调用,它接受一个传值的参数。

输出

Creating function declaration
Creating alpha
ctor-1
Calling `object_name`
ctor-2
Creating another Test within `object_name`.
ctor-1
17

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 1970-01-01
    • 2012-11-06
    相关资源
    最近更新 更多