2014-04-27 52 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();