为什么使用()声明对象时构造函数没有被调用?

11

可能重复:
为什么使用空括号调用没有参数的构造函数是错误的?

$ cat cons.cpp
#include <iostream>

class Matrix {
private:
    int m_count;

public:
    Matrix() {
        m_count = 1;
        std::cout << "yahoo!" << std::endl;
    }
};

int main() {
    std::cout << "before" << std::endl;
    Matrix m1();                         // <----
    std::cout << "after" << std::endl;
}
$ g++ cons.cpp
$ ./a.out
before
after
$

语法 Matrix m1(); 是什么意思?

我以为它和 Matrix m1; 是一样的,显然我错了。

4个回答

12

1
@Lazer:为了让自己信服,尝试使用m1(例如访问m1.m_count)... - Francesco
在C++11中,您可以对所有构造函数调用使用大括号,这避免了C++最令人困扰的解析问题,例如Matrix m1{}; - mark
这不是“最令人烦恼的解析”,最令人烦恼的解析是当您尝试声明对象并将值初始化的临时变量传递给一个或多个构造函数参数时。例如,A b(A())Matrix m1()只是一个常规函数声明。 - CB Bailey
@CharlesBailey:最令人烦恼的解析是尽可能将声明视为函数声明。这个问题确实只是又一个最令人烦恼的解析问题。 - Cheers and hth. - Alf

3

Matrix m1() 声明了一个不带参数且返回 Matrix 的函数。你可以通过向 Matrix 添加方法并尝试在 m1 上调用该方法来验证这一点:

#include <iostream>

class Matrix {
private:
    int m_count;

public:
    Matrix() {
        m_count = 1;
        std::cout << "yahoo!" << std::endl;
    }
    void foo() {}
};

int main() {
    std::cout << "before" << std::endl;
    Matrix m1();
    m1.foo();
    std::cout << "after" << std::endl;
}

出现错误:请求访问非类类型“Matrix()”的成员“foo”


1

从 C 语言的角度来思考:

int data_member();

实际上是一个接受 void 参数并返回 int 类型的函数原型。当你将它修改为:

T data();

它仍然是一个函数声明,返回 T。当你需要将其声明为变量时,你需要这样做:

T data; // int data;

0
这将实现你想要做的事情:
int main() {
    std::cout << "before" << std::endl;
    Matrix m1;                         // <----
    std::cout << "after" << std::endl;
}

在C++中,如果你用括号初始化一个变量,实际上它声明了一个不带参数并返回该类型的函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接