2014-04-27 50 views
1

作爲一名新的C++愛好者,我仍在努力理解使用「新」創建的類對象的範圍。我認爲我通過使用「new」實例化動態對象來讀取該類,因此類(和成員)可以被程序的所有部分直接訪問(例如,在其他函數內),因爲它不是在堆棧上創建的。使用「新」的類範圍

在下面的代碼中,我在構造函數中將'tesValue1'的初始值設置爲「111」,然後嘗試在「check_accessibility」函數中將其更新爲「222」。這不能編譯錯誤「myGeneralVars」沒有在這個[函數調用]範圍內聲明。

任何幫助,非常感謝。

//main.cpp 
#include <iostream> 
using namespace std; 

class generalVars 
{ 
private:  

public: 
    //data attributes 
    int testValue1; 

    //constructor 
    generalVars() 
    { 
     testValue1= 111; 
    } 

    ~generalVars(void) 
    { 
     cout << "destructor code here" << endl; 
    }; 

}; 

void check_accessibility() { 
    myGeneralVars->testValue1= 222; 
} 

int main(int argc, char *argv[]) 
{ 
    generalVars* myGeneralVars = new generalVars; //create on heap 
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //value set in constructor 
    check_accessibility(); //sets testValue to new value 
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //want "222" 

    delete myGeneralVars; //delete from heap 
    return 0; 
} 
+6

誰使用的措辭做了一個可怕的工作。它的*可訪問性*不是在玩什麼;它的對象的**生命**。唯一未完成的對創建對象的引用仍然只在局部變量中。 – WhozCraig

+2

不幸的是,很多人在生命週期中(當一個對象被創建和銷燬時 - 一種運行時概念)混淆了範圍(程序中的某個名稱是可見的 - 編譯時間概念)。但他們非常不同。 –

回答

0

既然你是一個業餘愛好者和初學者,讓我們你在正確的軌道上早讓你從你的愛好更多的樂趣和享受。

考慮我在這裏提出用人原則,這將使你的程序更優雅,堅固耐用,美觀,又生長在複雜的變化。

//main.cpp 
#include <iostream> 
#include <memory> 
using namespace std; 

class generalVars 
{ 
private:  

public: 
    //data attributes 
    int testValue1; 

    //constructor 
    generalVars() 
    : testValue1(111) 
    { 
    } 

    ~generalVars(void) 
    { 
     // if the class is carefully written using std:: objects 
     // you will rarely need to define a destructor 
     cout << "destructor code here" << endl; 
    }; 

}; 

// pass a reference to a mutable object to ensure that logic 
// is performed on the object and not on its lifetime 
void check_accessibility(generalVars& gv) { 
    gv.testValue1= 222; 
} 

int main(int argc, char *argv[]) 
{ 
    unique_ptr<generalVars> myGeneralVars(new generalVars); //create on heap *safely* 
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //value set in constructor 
    check_accessibility(*myGeneralVars); //sets testValue to new value 
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //want "222" 

    // no delete necessary - unique_ptr's destructor takes care of it 
    return 0; 
} 

輸出:

Compiling the source code.... 
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1 

Executing the program.... 
$demo 
Main testvalue1 = 111 
Main testvalue1 = 222 
destructor code here 
+0

謝謝。這絕對是解決它 - 我需要做一些關於「unique_ptr」的研究。我的初衷是通過使用一個全局可訪問的對象來創建一個'全局變量列表',該對象通過一個存儲機制實例化,該存儲機制將持續該程序的生命週期。這就是說,上述是實現這一目標的良好機制嗎?由於我是初學者,我正在尋找'易於理解但功能強大'的方法。 –

+0

做一個谷歌搜索'C++單身模式'。我認爲這會給你想要的。並不是說我是「全球可用」對象的粉絲,但有時你無法擺脫它。 –

0

在函數check_accessibility中,您使用尚未聲明的名稱myGeneralVars。

void check_accessibility() { 
    myGeneralVars->testValue1= 222; 
} 

所以編譯器發出錯誤信息。

在使用任何名稱之前,必須聲明它。

你可以寫的函數通過以下方式

void check_accessibility(generalVars* myGeneralVars ) { 
    myGeneralVars->testValue1= 222; 
} 

,並把它作爲

check_accessibility(myGeneralVars); 
2

它決定你的壽命。

C++使用存儲持續時間的概念:對象的生命週期取決於其實例化的位置和方式。有三(四)類型的存儲持續時間:

  • 靜態存儲時間:對象將在程序開始時被初始化,並會在節目結束被破壞。全局變量和靜態類屬性具有靜態存儲持續時間。

  • 自動存儲持續時間:對象的生存期由變量中聲明的範圍的壽命定義所以局部變量的生存期啓動功能啓動時,並且當函數結束結束。對於非靜態類數據成員也是如此:它的生命週期始於對象的生命週期開始,並在對象的生命週期結束時結束。

  • 動態存儲持續時間:該目的使用newdelete動態存儲器創建的,而壽命是由用戶確定的。當用戶確實開始使用壽命new時,壽命終止的時間爲delete

查看this documentation page瞭解更多信息。

在你的情況下,你使用一個指針變量來保存它的內存地址(對象的位置)來實例化一個具有動態存儲持續時間的對象。由於你永遠不會對該指針做delete,所以對象的生命週期永遠不會結束:這就是內存泄漏。

此外,您嘗試訪問其他功能(check_accessibility)一個函數(主)定義的變量。當然,這個變量不可見。但這與動態存儲持續時間無關,它只是一個簡單的名稱查找問題。誰告訴你存儲時間有關係或取決於名稱/變量可訪問性是完全錯誤的。

+0

謝謝。這開始有意義。我的最終目標是實例化一個對象,該對象包含一個程序不同部分所需的變量長列表,而不必每次都將該列表傳遞給函數,而無需創建全局變量。在這種情況下,我應該使用靜態存儲並在每次調用需要對象變量的函數時傳遞指向該對象的指針(如其他一些響應所示)?另外,我認爲我的程序最後的刪除將解決內存泄漏情況。 –

0

myGeneralVars不是由你的函數check_accessibility()知道,所以你不能訪問變量。相反,嘗試將它作爲參數傳遞。

void check_accessibility(generalVars* genVar) { 
    genVar->testValue1= 222; 
} 

int main(int argc, char *argv[]) 
{ 
    generalVars* myGeneralVars = new generalVars; //create on heap 
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //value set in constructor 
    check_accessibility(myGeneralVars); //sets testValue to new value 
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //want "222" 

    delete myGeneralVars; //delete from heap 
    return 0; 
} 
0

myGeneralVar僅在main()作用域內有效,所以check_accessibility()無法訪問它。您必須先在全局範圍內(外部函數定義)聲明它,或者將它作爲參數傳遞給main()中的check_accessibility()。請記住,您可能認爲主要功能不是全球範圍內的。 main()只是一個像其他函數一樣的函數,它有自己的範圍。

+0

在你的回答中,你指出「你必須在全局範圍內(函數定義之外)或......」聲明它。你能否提供關於如何完成的細節? –

+0

的#include INT I; int main(){cout << i << endl; } – user3556781

+0

只需在定義之外聲明它。粗略地說,如果編譯器在本地作用域中找不到變量,它將搜索包含本地作用域的作用域,依此類推,直至找到有效變量。全局範圍是您定義主函數和其他函數的地方,因此在其中聲明一個變量意味着該變量在其後的每個其他函數或類都是「可訪問的」。 (我沒有在例子中初始化變量,但是它對聲明的編譯器是完全有效的。) – user3556781

0

此外,可以定義內部generalVars類check_accessibility()函數和從主調用它作爲 mygeneralVars-> check_accessibility();