2016-06-24 4 views
2

Ich möchte eine benutzerdefinierte String-Klasse für C++ machen. Aber wenn ich dies tun:C++ - '(const char *)' nicht im Geltungsbereich deklariert?

g++ test.cpp sys/Base.h sys/Base.cpp 

ich diesen Fehler:

sys/Base.cpp: In function 'const char* Base::toChar()': 
sys/Base.cpp:57:13: error: 'strval' was not declared in this scope 
     return strval; 
      ^
sys/Base.cpp: In function 'std::string Base::toStr()': 
sys/Base.cpp:60:20: error: 'strval' was not declared in this scope 
     return string(strval); 
        ^

test.cpp

#include "sys/Base.h" 
int main() { 
    Base::write("Hello there.\n"); 
    return 0; 
} 

sys/base.h

// Header file handling 
#ifndef ARAVK_BASE_H 
#define ARAVK_BASE_H 

// Includes 
#include <string> 

// Global variables 
#define EXIT_YAY 0 
#define EXIT_ERR 1 

using namespace std; 

namespace Base { 
    // Classes: 
     class String { 
       static const char* strval; 
      public: 
       // Constructors: 
        String(); 
        String(char[]); 
        String(const char*); 
        String(string); 
       // Destructors: 
        ~String(); 

       // Operators: 
        // = 
         void operator=(const String&); 
         void operator=(const char*&); 
         void operator=(const string&); 

       // Conversion: 
        const char* toChar() const; 
        string toStr() const; 
     }; 
    // Functions: 
     // Input-Output: 
      // Write: 
       void write(String); 
       void write(string); 
       void write(const char*); 
      // Read: 
       String read(); 

     // Executing: 
      String run(String); 
} 
#endif 

sys/Basis .cpp

// Including 
#include "Base.h" 
#include <string> 
#include <stdio.h> 
#include <stdlib.h> 
#include <cstdio> 
#include <iostream> 
#include <memory> 
#include <stdexcept> 

// Global variables 
#define EXIT_ERR 1 
#define EXIT_YAY 0 

/* ------------------------ */ 
using namespace std; 

namespace Base { 
    // Classes 
     // String functions 
      // Constructors 
       String::String() { 
        const char* strval = ""; 
       } 
       String::String(const char* str) { 
        const char* strval = str; 
       } 
       String::String(string str) { 
        const char* strval = str.c_str(); 
       } 
       String::String(char str[]) { 
        const char* strval = str; 
       } 
      // Destructors 
       String::~String() { 
        delete strval; 
       } 
      // Operators 
       // = 
        void String::operator=(const String &strp) { 
         strval = strp.toChar(); 
        } 
        void String::operator=(const char* &strp) { 
         strval = strp; 
        } 
        void String::operator=(const string &strp) { 
         strval = strp.c_str(); 
        } 
      // Conversion: 
       const char* toChar() { 
        return strval; 
       } 
       string toStr() { 
        return string(strval); 
       } 

    // Functions: 
     // Input-Output: 
      // Write 
       void write(String str)  { printf(str.toChar()); } 
       void write(const char* str) { printf(str);    } 
       void write(string str)  { printf(str.c_str()); } 
      // Read 
       String read()      { char str[100]; scanf("%s", str); return String(str); } 
       //TODO: More to come 

     // Executing 
      /*String run(String command) { 
       const char* cmd = command.toChar(); 
       char buffer[128]; 
       string result = ""; 
       std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose); 
       if (!pipe) throw runtime_error("popen() failed!"); 
       while (!feof(pipe.get())) { 
        if (fgets(buffer, 128, pipe.get()) != NULL) 
         result += buffer; 
       } 
       return String(result); 
      }*/ 
      String run(String command) { 
       char buffer[128]; 
       std::string result = ""; 
       const char* cmd = command.toChar(); 
       FILE* pipe = popen(cmd, "r"); 
       if (!pipe) throw std::runtime_error("popen() failed!"); 
       try { 
         while (!feof(pipe)) { 
           if (fgets(buffer, 128, pipe) != NULL) 
             result += buffer; 
         } 
       } catch (...) { 
         pclose(pipe); 
         throw; 
       } 
       pclose(pipe); 
       return String(result); 
      } 

} 

Ich bin mir nicht sicher, warum das passiert. Ich denke, es hängt damit zusammen, wie ich das const char * 'strval' deklariert/definiert habe. Kann jemand helfen? P. S: Wenn die Antwort zu groß ist, ist dieses Projekt auf Github: AravK/C-Applications

+0

Ihre 'String' Konstruktoren alle deklarieren eine lokale Variable, die sofort zerstört wird. Was versuchst du zu machen? –

+0

Ihr 'const char * strval' scheint nicht' statisch' zu sein – LibertyPaul

+1

Es gibt viele Dinge, die mit Ihrem Code nicht stimmen. Dies ist völlig in Ordnung, da es ein Anfänger in C++ ist, aber es wäre eine sehr breite Antwort, um auf alle Probleme in Ihrem Code hinzuweisen. Das ist nicht wirklich geeignet für diese Seite. Ich würde empfehlen, ein [gutes Buch für C++] (https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) zu überprüfen. – Zulan

Antwort

3

Lassen Sie uns einen Blick auf Ihre Konstruktor nehmen:

  String::String() { 
       const char* strval = ""; 
      } 

Dies erklärt eine lokale Variable strval genannt. Die Variable ist lokal für den Konstruktor; Es existiert nicht, sobald die Ausführung des Konstruktors abgeschlossen ist.

Was Sie stattdessen benötigen, ist eine Membervariable - deklarieren Sie es innerhalb der Klasse, aber nicht innerhalb einer Member-Methode oder Konstruktor. In der Tat haben Sie es bereits als solche in der Header-Datei definiert:

class String { 
      static const char* strval; 

Also, die const char * von Ihrem Konstruktor entfernen und eine Klasse-Qualifikation hinzuzufügen, so dass die Leitung eine Zuweisung an die bestehenden Variable wird, anstatt Schaffung eines lokalen:

  String::String() { 
       String::strval = ""; 
      } 

Und auch die return-Anweisung ändern, die Sie den Fehler geben:

   return String::strval; 

Oder vielleicht - , und dies ist wahrscheinlich, was Sie wirklich wollte - den static Qualifier aus der Variablendefinition und den Konstruktor ändern stattdessen nur:

  String::String() { 
       strval = ""; 
      } 

Darüber hinaus Ihre destructor falsch delete s Daten, die nicht notwendigerweise dynamisch zugewiesen wurde, oder die zu einem anderen Objekt gehören können:

  String::~String() { 
       delete strval; 
      } 

Dies erfordert eine Überarbeitung. Im Moment ist die einfachste Lösung, die delete strval insgesamt zu entfernen.

Ihre read() Funktion stiftet möglicherweise einen Pufferüberlauf, durch scanf mit ("% s") mit einer festen Größe Puffer und unbekannten Eingangsgröße:

char str[100]; scanf("%s", str); return String(str); 

Schließlich Befehlszeile:

g++ test.cpp sys/Base.h sys/Base.cpp 

... sollte nicht enthalten die Header-Datei (Base.h). Sie geben die Einheiten an, die Sie kompilieren möchten, und Base.h ist bereits in Base.cpp enthalten. es ist keine eigenständige Einheit, die inkompiliert werden sollte.

+0

Bitte beachten Sie, dass diese Antwort bei weitem nicht erschöpfend ist. Alles über Speicherverwaltung im Code ist absolut falsch. Obwohl ich keine erschöpfende Antwort auf diese Frage erwarte, ist es meiner Meinung nach irreführend, eine unvollständige Antwort zu geben, die nur die Zusammenstellung behebt. – Zulan

+0

@Zulan Wenn Sie auf bestimmte Probleme hinweisen können, werde ich sie gerne in die Antwort bearbeiten. (Haben Sie etwas über den Destruktor notiert - noch etwas?) – davmac

+0

Zum Beispiel 'char str [100]; scanf ("% s", str); return String (str); 'kombiniert einen Pufferüberlauf mit der Übertragung des Besitzes des Stack-Speichers. Alles über die Erinnerung ist falsch. Diese Fragen sind zu weit gefasst, um hier zu antworten, aber das OP muss wissen, dass er mehr über die Grundlagen erfahren sollte. – Zulan

0

ja Sie haben die Variable in Ihrer Klasse nicht als Feld definiert. gibt es 3 Einheimische Deklaration in Ihren Konstruktoren. fügen Sie es einfach so hinzu, wie Sie es in der Kopfzeile getan haben.

static const char* strval 

und entfernen Sie die Definition in Ihren Konstruktoren. Behalte einfach den Aufgabenbereich. Grüße