我遇到了一些与std::ofstream
相关的奇怪编译错误。比方说,我有一个头文件ofstream_test.hpp
,和它对应的源文件ofstream_test.cpp
。
ofstream_test.hpp
:
#include <iostream>
#include <fstream>
class OfstreamTest {
public:
OfstreamTest();
std::ofstream m_strm_obj("output.txt");
};
ofstream_test.cpp
:
#include "ofstream_test.hpp"
OfstreamTest::OfstreamTest() {
std::cout << "ctor" << std::endl;
}
main.cpp
:
#include "ofstream_test.hpp"
int main(int argc, char const *argv[]) {
OfstreamTest obj;
return 0;
}
错误:
$ g++ -std=c++17 main.cpp ofstream_test.cpp
In file included from main.cpp:1:0:
ofstream_test.hpp:8:30: error: expected identifier before string constant
std::ofstream m_strm_obj("output.txt");
^~~~~~~~~~~~
ofstream_test.hpp:8:30: error: expected ‘,’ or ‘...’ before string constant
In file included from ofstream_test.cpp:1:0:
ofstream_test.hpp:8:30: error: expected identifier before string constant
std::ofstream m_strm_obj("output.txt");
^~~~~~~~~~~~
ofstream_test.hpp:8:30: error: expected ‘,’ or ‘...’ before string constant
如果我尝试使用open
方法,我也会得到编译错误(虽然有点不同):
ofstream_test.hpp
:
class OfstreamTest {
public:
OfstreamTest();
std::ofstream m_strm_obj;
m_strm_obj.open("output.txt");
};
ofstream_test.cpp
:
OfstreamTest::OfstreamTest() {
std::cout << "ctor" << std::endl;
}
错误:
$ g++ -std=c++17 main.cpp ofstream_test.cpp
In file included from main.cpp:1:0:
ofstream_test.hpp:9:5: error: ‘m_strm_obj’ does not name a type
m_strm_obj.open("output.txt");
^~~~~~~~~~
In file included from ofstream_test.cpp:1:0:
ofstream_test.hpp:9:5: error: ‘m_strm_obj’ does not name a type
m_strm_obj.open("output.txt");
^~~~~~~~~~
然而,对于以下情况,我没有得到任何编译错误:
- 案例1:
class OfstreamTest {
public:
OfstreamTest();
};
OfstreamTest::OfstreamTest() {
std::cout << "ctor" << std::endl;
std::ofstream m_strm_obj("output.txt"); // initialized the object in source file, instead of header file
}
- 案例2:
class OfstreamTest {
public:
OfstreamTest();
std::ofstream m_strm_obj{"output.txt"}; // just changed () to {}
};
OfstreamTest::OfstreamTest() {
std::cout << "ctor" << std::endl;
}
- 案例3:
class OfstreamTest {
public:
OfstreamTest();
std::ofstream m_strm_obj; // declared the object but didn't initialize in the header file
};
OfstreamTest::OfstreamTest() {
std::cout << "ctor" << std::endl;
m_strm_obj.open("output.txt");
}
我不明白为什么?
将非常感谢一个深入的答案(或至少有一些参考链接的答案)!
std::ofstream m_strm_obj("output.txt");
在将m_strm_obj
声明为类成员时是无效的语法(将其声明为局部变量时是可以的)。
你不能初始化/构造一个类数据成员(不管它的类型),在类范围内声明成员的地方用括号括起来。c++标准的语法规则根本不允许这样做,以避免将编译器与成员函数声明混淆。
但是,从c++ 11开始,可以在类作用域使用花括号初始化/构造类数据成员,例如:
class OfstreamTest {
public:
OfstreamTest();
std::ofstream m_strm_obj{"output.txt"};
};
否则,可以使用父类构造函数的成员初始化列表,例如:
class OfstreamTest {
public:
OfstreamTest();
std::ofstream m_strm_obj;
};
OfstreamTest::OfstreamTest() : m_strm_obj("output.txt") {
std::cout << "ctor" << std::endl;
}
,或者在构造函数体内使用open()
,例如:
class OfstreamTest {
public:
OfstreamTest();
std::ofstream m_strm_obj;
};
OfstreamTest::OfstreamTest() {
std::cout << "ctor" << std::endl;
m_strm_obj.open("output.txt");
}