2017-01-07 1 views
-3

Ich habe eine Klasse IStream2:Warum initialisiert ein zweites Objekt mein erstes Objekt?

class IStream2 { 
    private: 
     char* fn; 
    public: 
     IStream2(char* filename); 
     char* get_filename(); 
}; 


IStream2::IStream2(char *filename) { 
    strcpy(fn, filename); 
} 
char * IStream2::get_filename() { 
    return fn; 
} 

Und hier ist der Hauptcode:

vector<IStream2> istreams; 

char fn[] = "file1.txt"; 
IStream2 reader2 = IStream2(fn); 
istreams.push_back(reader2); 

char fn2[] = "file2.txt"; 
IStream2 reader3 = IStream2(fn2); 
istreams.push_back(reader3); 
cout << istreams[0].get_filename() << endl; 

Er druckt file2.txt aber ich erwartete file1.txt. Ich weiß, dass ich Zeichenfolge verwenden sollte, aber ich möchte dieses Problem beheben.

+7

wie haben Sie Speicher für fn zugewiesen? (also hat die strcpy irgendwo zu kopieren) – Jimmy

+0

Vielleicht, weil Sie 'fn' in beiden Fällen verwenden? Ändern Sie den Namen des zweiten 'char *' –

+2

Dieser Code ist falsch, da Sie 'fn' zweimal definiert haben. Gib uns den richtigen Code, der das Problem verursacht. Versuchen Sie auch, 'fn'-Member zuzuordnen, wenn Sie nicht undefiniert sind. –

Antwort

2
IStream2::IStream2(char *filename) { 
    strcpy(fn, filename); 
} 

Ordnet keinen Speicherplatz für fn zu. strcpy(fn, filename); ruft ein undefiniertes Verhalten auf, das in einen beliebigen Speicher schreibt fn Punkte, und danach sind alle Wetten aus. Das Programm könnte alles tun.

Die richtige Antwort ist std::string

class IStream2 { 
private: 
    std::string fn; 
public: 
    IStream2(const char* filename); // note const. if not modifying a passed rference, 
            // mark it const. The compiler can make optimizations 
            // and can catch mistakes for you 
            // also the function can now receive string literals 
    const char* get_filename(); // another const this is because a string won't 
           // easily give you a non const pointer 
}; <-- note the added ; 

IStream2::IStream2(const char *filename): fn(filename) { 
} 
const char * IStream2::get_filename() { 
    return fn.c_str(); // get the char array from the string 
} 

zu verwenden, aber ich vermute, dies ist eine Übung mit Klassen in schriftlicher Form C, also zurück in die Steinzeit gehen wir. Das ist viel mehr Arbeit, weil wir den ganzen Speicher selbst verwalten müssen. Zum Beispiel müssen wir die Dreiregel einhalten. What is The Rule of Three?

Seufz.

class IStream2 { 
private: 
    char* fn; 
public: 
    IStream2(const char* filename); // note const char * 
    ~IStream2(); // need destructor to clean up fn. This means we need to 
       // comply with the Rule of Three 
    IStream2(const IStream2 & src); // copy constructor 
    IStream2 & operator=(IStream2 src); // assignment operator 
    char* get_filename(); // Note: by returning a non const pointer here we 
          // allow the caller to tamper with the contents of 
          // fn and even delete it. This defeats the point 
          // of declaring fn private, so avoid doing this. 
}; 

IStream2::IStream2(const char *filename) { 
    fn = new char[strlen(filename) +1]; // allocate storage. 
             // The +1 is to hold the string's NULL terminator 
    strcpy(fn, filename); 
} 
// implement copy constructor 
IStream2::IStream2(const IStream2 & src) { 
    fn = new char[strlen(src.fn) +1]; 
    strcpy(fn, src.fn); 
} 
// implement destructor 
IStream2::~IStream2() 
{ 
    delete[] fn; 
} 
// implement assignment operator. Using Copy And Swap Idiom 
IStream2 & IStream2::operator=(IStream2 src) 
{ 
    std::swap(fn, src.fn); 
    return *this; 
} 
char * IStream2::get_filename() { 
    return fn; 
} 


int main() 
{ 
    vector<IStream2> istreams; 

    const char* fn = "file1.txt"; // note const char *. string literals may be 
            // read-only memory and can't be changed 
    IStream2 reader2 = IStream2(fn); 
    istreams.push_back(reader2); 

    const char* fn2 = "file2.txt"; // and again const char * 
    IStream2 reader3 = IStream2(fn2); 
    istreams.push_back(reader3); 
    cout << istreams[0].get_filename() << endl; 
    return 0; 
} 

Da wir mit Dinosaurier wresting, werde ich nicht mit dem Rule of Five stören und Operationen verschieben, sondern sehen, wie viel ärgerlicher, es zu haben, ist dies der falsche Weg zu tun?

Mehr auf Copy And Swap Idiom

Verwandte Themen