简体   繁体   中英

How can I define an object as one type, then later declare it as a sub-type?

I have some code that needs to read in data, either from an istringstream or an ifstream. I don't know much about C++, but my experience in other languages tells me I should just have a variable that's an istream (the parent type of ifstream and istringstream), and then later set it to either an istringstream or an ifstream. Here's what this might look like in, say, Java:

String word;
IStream stream;

if (someCondition) {
    stream = new IStringStream("banana");
} else {
    stream = new IFStream("apple.txt");
}

while (word = is.read()) {
    // do some stuff
}

This type of syntax would work no problem in Java and other similar languages, but I can't get it to work in C++. Here's what my code looks like right now:

string word;
istream stream;

if (someCondition) {
    string mystr = "banana";
    istringstream stream(mystr);
} else {
    string myfile = "apple.txt";
    ifstream stream(myfile);
}

while(stream >> word) {
    // do some stuff
}

This doesn't compile, with the error on the 2nd line: "no matching constructor for initialization of 'istream' (aka 'basic_istream')". What can I change to make the C++ code work like the Java pseudocode example I wrote above does?

Since you are coming from Java, a quick rule of thumb is that for polymorphic objects you need a pointer (asterisk * ), a reference (ampersand & ), a smart pointer, or some other way of setting up indirection.

Here is an example of the syntax that would fix the problem:

string word;
istream *stream;

if (someCondition) {
    string mystr = "banana";
    stream = new istringstream(mystr);
} else {
    string myfile = "apple.txt";
    stream = new ifstream(myfile);
}

while((*stream) >> word) {
    // do some stuff
}

delete stream;

Note: This solution is not ideal, because you end up deleting the stream manually. A better approach would rely on a smart pointer, which deletes your object automatically.

You should put the part that uses the stream in a function that takes a std::istream& and then just pass in whatever you want to use.

#include <iostream>
#include <sstream>
#include <fstream>

void useStream(std::istream& stream) {
    std::string word;
    while (stream >> word)
        std::cout << word << ' ';
}

int main() {
    if (someCondition) {
        std::string str = "The best program in the world";
        std::stringstream foo(str);
        useStream(foo);
    }
    else {
        std::ifstream file("text.txt");
        useStream(file);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM