为什么 fstream::open() 需要一个 C 样式的字符串

Why does fstream::open() expect a C style string?

本文关键字:一个 样式 字符串 fstream open 为什么      更新时间:2023-10-16

所以我正在运行这段示例代码:

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main() {
  ifstream inFile;
  string str;
  cout << "nEnter file name : ";
  cin >> str;
  try {
    inFile.open(str);
    if(!inFile)
      throw exception();
  } catch(exception e) {
    cout <<"nAn exception was caught. file does not exist. ";
    return 1;
  }
  return 0;
}

它给了我一个编译器错误:

test.cpp:14:13: error: no viable conversion from 'string' (aka 'basic_string<char>') to 'const char *'
inFile.open(str);
            ^~~
/usr/include/c++/4.2.1/fstream:517:24: note: passing argument to parameter '__s' here
      open(const char* __s, ios_base::openmode __mode = ios_base::in)

我查找了函数原型:

void open (const char* filename,
           ios_base::openmode mode = ios_base::in | ios_base::out);
void open (const string& filename,
           ios_base::openmode mode = ios_base::in | ios_base::out);

为什么 fstream::open() 需要一个 const 字符串/const char* ?文件名可以从任何地方(从用户那里,如上例所示)获取,在这种情况下,将str变成const string无济于事。我能够通过使用str.c_str()来让它工作,但是有人可以帮助我理解为什么在文件打开方法中强制执行恒定性吗?为什么不允许我按原样使用字符串,而不必使用 char* 或将其转换为 c 样式的字符串?

您可以将非const对象传递给采用const引用的函数。

问题是您没有(或尚未启用)C++11 支持,因此缺少string重载。如果您坚持使用 2011 年之前的库,那么您唯一的选择是使用 c_str() 来获取 C 样式的字符串指针。

C++11 的(使用 -std=c++0xstd=c++11 标志启用)

void open (const string& filename,
           ios_base::openmode mode = ios_base::in | ios_base::out);

不会导致非常量字符串对象出现任何问题。

const string &有助于避免不必要的字符串对象复制

open const char*的事实并不意味着你不能通过常规char*传递它。 char*可以转换为const char*,只是不能反过来(除非你使用const_cast,但这些都是邪恶的)。

这个声明只是说"open接受一个字符串作为输入,它承诺不修改内容"。

您的代码可以使用当前标准(C++11)进行编译,遗憾的是,我知道的任何编译器都没有默认使用该标准。

您误解了函数签名的语法:

为什么 fstream::open() 需要一个 const 字符串/const char* ?这 文件名可以从任何地方获得(从用户那里,如在 上面的例子),并且将 str 变成一个 const 字符串无济于事 那个案子。

签名如下,供参考:

void open (const char* filename, ios_base::openmode mode = ios_base::in | ios_base::out);
void open (const string& filename, ios_base::openmode mode = ios_base::in | ios_base::out);

第一个重载采用const char*(例如,指向常量字符数组的指针)。第二个重载需要const std::string&(例如,对常量 std::string 的引用)。

它不是一个const std::string,而是对字符串的引用。 它声明该函数不会修改字符串,并且您正在传递对原始字符串的引用(而不是复制它)。 您可以将非 const 字符串传递给需要 const 字符串的函数,而不会出现问题(不需要转换/强制转换)。

您最初问题的答案(为什么需要const char*?)并不复杂:流库和字符串库是由不同的人群并行开发的。 在早期的标准中,他们没有合并开发。 这已在C++11中得到解决。