2016-06-24 102 views
2

我想爲C++創建一個自定義的String類。但是,當我這樣做:C++ - '(const char *)'未在範圍內聲明?

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

我得到這個錯誤:

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 /基地.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); 
      } 

} 

我不知道爲什麼會發生這種情況。我認爲這與我如何聲明/定義const char *'strval'有關。任何人都可以幫忙嗎? P.S:如果答案是太大了,這個項目是在Github上:AravK/C-Applications

+0

你的'String'構造函數都聲明瞭一個立即被銷燬的局部變量。你想做什麼? –

+0

你的'const char * strval'似乎不是'static' – LibertyPaul

+1

你的代碼有很多錯誤。作爲C++的初學者來說,這是非常好的,但是要指出代碼中的所有問題將是一個非常廣泛的答案。這不是真的適合這個網站。我會推薦檢查出一本[C++的好書](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)。 – Zulan

回答

3

讓我們來看看你的構造:

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

聲明一個名爲strval當地變量。該變量對構造函數是本地的;它在構造函數的執行完成後不存在。

你需要的是一個成員變量 - 在類中聲明它,但在成員方法或構造函數中不是而是。事實上,你已經將它定義爲這樣的頭文件:

class String { 
      static const char* strval; 

那麼,請從您的構造函數中的const char *並添加類資格,使該行成爲分配給現有的變量,而不是創建一個本地的:

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

,改變這是給你的錯誤return語句:

   return String::strval; 

也許 - ,這有可能是你真正想要的 - 從變量定義中移除static預選賽,並改變構造函數,而不是隻是:

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

而且,這是不一定動態分配你的析構函數不正確delete s的數據,或可能屬於另一個對象:

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

這需要重新工作。目前最簡單的解決方案是完全刪除delete strval

read()功能潛在鼓動緩衝區溢出,通過使用的scanf( 「%S」)配有一個固定大小的緩衝區和未知的輸入大小:

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

最後,命令行:

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

...應該不是包含頭文件(Base.h)。您正在指定要編譯的單元,並且Base.h已包含在Base.cpp中;它不是一個獨立的單元,應該單獨編譯。

+0

請注意,這個答案是非常詳盡的。代碼中關於內存管理的一切都是錯誤的。雖然我並不期望對這個問題做詳盡的回答,但我認爲提供一個不完整的解決方案會誤導我們,只是修正了這個問題。 – Zulan

+0

@Zulan如果你能指出任何具體問題,我會很樂意將它們編輯爲答案。 (把關於析構函數的東西放進去了 - 其他東西?) – davmac

+0

以'char str [100];爲例。 scanf(「%s」,str);返回String(str);'它將緩衝區溢出與轉移堆棧內存所有權結合起來。關於記憶的每一件事都是錯誤的。這些問題太廣泛,無法在這裏回答,但OP需要知道他應該更多地瞭解基礎知識。 – Zulan

0

是的,你沒有將你的班級中的變量定義爲一個字段。 在你的構造函數中有3個當地人的聲明。 只需按照您在標題中完成的方式添加即可。

static const char* strval 

並刪除您的構造函數中的定義。只要保留分配部分。 關於