Frage

So I'm running this bit of sample code :

#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;
}

And it gave me a compiler error :

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)

I looked up the function prototype :

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);

Why does fstream::open() expect a const String/ const char* ? The filename could be obtained from anywhere (from a user, like in the example above), and making str into a const string doesn't help in that case. I was able to get it to work by using str.c_str() instead, but could someone help me understand why the const-ness has been enforced in the file open method? Why shouldn't I be allowed to use a string as is, without having to use a char* or convert it into a c-style string?

War es hilfreich?

Lösung 5

You are misunderstanding the syntax for the function signatures:

Why does fstream::open() expect a const String/ const char* ? The filename could be obtained from anywhere (from a user, like in the example above), and making str into a const string doesn't help in that case.

The signatures are below for reference:

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);

The first overload takes a const char* (e.g. a pointer to a constant character array). The second overload takes a const std::string& (e.g. a reference to a constant std::string).

It is not a const std::string, but a reference to a string. It is stating that the function will not modify the string, and you are passing a reference to the original (instead of copying it). You can pass a non-const string to a function that requires a const string without an issue (there is no conversion/cast required).

The answer to your original question (Why does it take a const char*?) is not all that complicated: The stream libraries and the string libraries were developed in parallel by different groups of people. In the early standards, they didn't merge the development. That has been addressed in C++11.

Andere Tipps

You can pass a non-const object to a function that takes a const reference.

The problem is that you don't have (or haven't enabled) C++11 support, so the string overload is missing. If you're stuck with a pre-2011 library, then your only option is to use c_str() to get a C-style string pointer.

C++11's (enabled with -std=c++0x or std=c++11 flag )

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

won't cause any issue with non-const string object.

The const string & helps to avoid unnecessary copying of string object

The fact that open takes a const char* doesn't mean you can't pass it a regular char*. char* can be converted to const char*, just not the other way around (unless you use const_cast, but those are evil).

This declaration is just saying "open takes a character string as input, and it promises not to modify the contents".

you code compiles fine with the current standard (C++11), which sadly is not used by default by any compiler I know of.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top