Question

As a new C++ hobbyist, I am still wrestling with understanding scope for class object created using "new". I thought I read that by instantiating a dynamic object using "new", the class (and members) would be accessible by all parts of the program directly (for example, within other functions) since it is not created on the stack.

In the code below, I set the initial value of 'tesValue1' to "111" in the constructor, and then try to update it to "222" in the 'check_accessibility' function. This fails to compile with the error "myGeneralVars" not declared within this [the function call] scope.

Any assistance is greatly appreciated.

//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;
}
Was it helpful?

Solution 2

Since you're a hobbyist and a beginner, let's get you on the right track early so that you get more pleasure and enjoyment from your hobby.

consider the changes I have made here employing principles that will make your program more elegant, robust and pleasing as it grows in complexity.

//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;
}

output:

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

OTHER TIPS

It has the lifetime you decide.

C++ uses the concept of storage duration: The lifetime of an object depends on where and how its instantiated. There are three (Four) types of storage durations:

  • Static storage duration: The object will be initialized at program start and will be destructed at program finish. Global variables and static class attributtes have static storage duration.

  • Automatic storage duration: The lifetime of an object is defined by the lifetime of the scope the variable is declared in. So the lifetime of local variables starts when the function starts, and ends when the function ends. The same for non-static class data members: Its lifetime starts when the object's lifetime starts, and ends when the lifetime of the object ends.

  • Dynamic storage duration: The object is created on dynamic memory using new and delete, and the lifetime is determined by the user. When the user does new the lifetime starts, and when does deletethe lifetime ends.

See this documentation page for more information.

In your case, you instantiate an object with dynamic storage duration, using a pointer variable to hold its memory address (The location of the object). Since you never do a delete on that pointer, the lifetime of the object never ends: Thats a memory leak.

Also, you try to access a variable defined in one function (main) in other function (check_accessibility). Of course that variable is not visible out of main. But thats nothing to do with dynamic storage duration, its only a simple name lookup problem. Whoever tells you storage duration has something related or depending on name/variable accessibility was completely wrong.

myGeneralVars is not known by your function check_accessibility(), so you cannot access the variable. Instead, try to pass it as parameter.

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;
}

myGeneralVar is valid only inside the main() scope, so check_accessibility() has no access to it. You have to declare it before, either in global scope (outside function definition) or by passing it as argument to check_accessibility() inside main(). Keep in mind that the main function is not the global scope, as you might think. main() is just a function like others and has its own scope.

In function check_accessibility you use name myGeneralVars that was not yet declared.

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

So the compiler issues athe error.

Before using any name it has to be declared.

You could write the function the following way

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

and call it as

check_accessibility( myGeneralVars ); 

Also, you can define the check_accessibility() function inside generalVars class and call it from main as mygeneralVars->check_accessibility();

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top