为什么fstream :: open()期望一个C风格的字符串?

时间:2013-10-25 17:18:06

标签: c++ fstream c-strings

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

#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 String / const char *?文件名可以从任何地方获取(来自用户,如上例中所示),在这种情况下,将str转换为const string也无济于事。 我能够通过使用str.c_str()来使其工作,但有人可以帮助我理解为什么 const - 已经在文件打开方法中强制执行了吗?为什么不允许我按原样使用字符串,而不必使用char *或将其转换为c风格的字符串?

5 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:3)

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

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

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

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

答案 2 :(得分:2)

open占用const char*的事实并不意味着您无法将其传递给常规char*char*可以转换为const char*,而不是相反(除非你使用const_cast,但这些都是邪恶的。)

这个声明只是说“open将字符串作为输入,它承诺不会修改内容”。

答案 3 :(得分:2)

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

答案 4 :(得分:1)

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

  

为什么fstream :: open()期望一个const String / 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中得到解决。