What is Object Scope in Oop? - c++

Hi I read this definition on internet..
A destructor is a special member function of a class that is executed
whenever an object of it's class goes out of scope or whenever the
delete expression is applied to a pointer to the object of that class.
I tried this code..
#include <iostream>
using namespace std;
class Name{
public:
void Fun(){
cout << "Function" << endl;
}
Name(){
cout << "Constructor" << endl;
}
~Name(){
cout << "Destructor" << endl;
}
};
int main(){
Name obj;
obj.Fun();
cout << "End" << endl;
return 0;
}
It's calling destructor at the end of program..!! Mean object scope is the end of program? Sorry I'm little confused...

In your case the end of the scope of obj is at the end of the main function, but it could be any other scope depending on where you define obj. Example:
int main(){
// open a new scope here
{
// now 'obj' will be in the new scope
Name obj;
obj.Fun();
}
// the scope ended here, 'obj' destroyed now
cout << "End" << endl;
return 0;
}
You can find more information here, look at "Basic concepts" for "Scope" and "Lifetime".

Scope is a region in program that defines life time of objects defined within it. In nearly all cases it is defined by curly brackets. So when you have definition of function it's body defines a scope.
main is no special in any way in regard to definition of scope.
Some more cases:
int fun(){ // one scope
for(int i = 0; i < 1337; ++i){ // another scope
//note that i is defined within `for` scope not outside
}
if(true){ // same here
}
{ // you can even start and end scope at will
A a;
} // a will die here
{ // sometimes it is useful for redeclaring a variable, probably not best practice
A a; // this is legal
}
}

The object obj that you have created is a variable and as any variable it has scope. Scope is defined by curly brackets in which variable was created. In your case the scope of obj that you created is main function, because it is placed between curly brackets of that function. And when main function ends, your object is not available anymore (it is available only within that function) and that is why destructor is called.
You can also define scope of your own by just putting your object into curly brackets like that:
main(){
cout<<"scope of the main function"<<endl;
{
cout <<"scope where obj created"<<endl;
Name obj;
}
cout << "obj destroyed"<<endl;
cout << "End of main" <<endl;
}

In your case its C# program, In the case of object ends it availability after the program ends i.e. after the main is executed the object finds its destructor if it’s not available by programmer then its system generated destructor will be executed an it will destroy all the object and frees up the memory..

Related

Scope of an object created in a function

I have created an object of a class inside a function. The created object is passed as a parameter to another class. I expect that when I exit the function in which the object is created, the object must be destroyed.
Also any references to this object must be invalid, but I find that the object referenced after exiting the function is still valid. Trying to understand the scope of the object. The code snipped is given below.
class TextWidget
{
public:
TextWidget()
{
cout << "Constructor TextWidget" << endl;
}
TextWidget(int id)
{
_ID = id;
cout << "Constructor TextWidget" << endl;
}
~TextWidget()
{
cout << "Destructor TextWidget" << endl;
}
void printWidgetInstance()
{
cout << this << endl;
}
int _ID;
};
class AnotherWidget
{
public:
AnotherWidget()
{
cout << "Constructor AnotherWidget" << endl;
}
~AnotherWidget()
{
cout << "Destructor AnotherWidget" << endl;
}
TextWidget* getTextWidget()
{
return _textWidget;
}
void setTextWidget(TextWidget* t)
{
_textWidget = t;
}
int getTextID() { return _textWidget->_ID; }
private:
TextWidget* _textWidget;
};
ButtonWidget b;
AnotherWidget a;
void fun()
{
TextWidget t(7);
b.setTextWidget(&t);
a.setTextWidget(&t);
a.getTextWidget()->printWidgetInstance();
b.getTextWidget()->printWidgetInstance();
}
int main()
{
fun();
cout << "TextWidget in AnotherWidget is ";
a.getTextWidget()->printWidgetInstance();
cout << "Text ID in a is " << a.getTextID() << endl;
getchar();
return 0;
}
OUTPUT
Constructor AnotherWidget
Constructor TextWidget
Before deleting TextWidget in class ButtonWidget 0x73fdf0
Before deleting TextWidget in class AnotherWidget 0x73fdf0
0x73fdf0
0x73fdf0
Destructor TextWidget
TextWidget in AnotherWidget is 0x73fdf0
Text ID in a is 7
A variable declared using automatic storage duration (not using new) has a lifetime of its scope. Accessing the variable outside the scope results in undefined behavior.
You need to understand what classes, objects, pointers and references are. Classes are code in memory, this code deals with the member variables. A class does not occupy any data memory. When you create a object you instantiate the class. This step will reserve some data memory for the local data of one object instance of the class. To access this instance you get a reference to the object (this). An object variable holds a pointer to the data memory of an instance of a class.
When an object gets destroyed the occupied memory block gets listed as free but not cleared. So if you still have a reference to that memory block you may access it. And as long as the system doesnt use this memory block for other purposes you still will find your bits and bytes there.
You may declare some variables:
long long_array[10];
myclass myobject;
These variables are stored sequential in one memory block. When you now access the memory behind the long_array through that array:
long_array[10] = 12345; // valid range is from long_array[0] to long_array[9]
Than you will overwrite the data of the object myobject.

C++: When is a destructor called before the last statement?

So I have some C++ code:
#include <iostream>
using namespace std;
class C {
public:
C() {i = 9; cout << "C0:" << i << endl;}
C(int i0) {i = i0; cout << "C1:" << i << endl;}
~C() {cout << "C2:" << i << endl;}
private:
int i;
};
void f(int i) {
C c(i);
}
int main(int argc, char* argv[]) {
for (int i = 0; i < 1; i++) {
cout << "X" << endl;
f(i);
cout << "Y" << endl;
}
}
And the output is:
X
C1:0
C2:0
Y
This is strange because the line C2:0 is part of the destructor which I've learned is called after the last statement. So my question is in what kind of situations are destructors called before the last statement?
Object C is created inside function f. So, C is destroyed when the f function scope ends, simply right after calling f(i) in main, f scope is destroyed, and the C object's destructor is called.
Automatic variables (your c in f()), are cleaned up when the stack they are on goes away.
So in this case, it's as your f(i) call is returning. For objects, this includes calling the destructor.
Globals and static variables are also cleaned up as your program exits, when it exits properly. If it exits via an uncaught exception, they may not be cleaned up (it's not required).
This is strange because the line C2:0 is part of the destructor which I've learned is called after the last statement.
The destructor is called after the last statement of the scope containing the variable which is an instance of a class.
C is created and destroyed within the scope of the f(int i) function so the destructor of C prints "C2:0". f finishes and only then Y is printed.

C++ - Scope of Variables Created in a Class Method

I'm trying to learn C++, and from my understanding if a variable goes out of scope then it is destroyed and its memory is reallocated. If I have a class and it's method creates a variable, shouldn't that variable be destroyed after the method call? For example:
class TestClass {
public:
struct Pair{
std::string name;
int value;
};
void addPair() {
//should be deleted after push_back is called?
Pair x = Pair{ std::string{ "Test Object " }, counter++ };
pairs.push_back(x);
}
void printPairs() {
for (int i = 0; i < pairs.size(); i++) {
std::cout << "pair { " << pairs[i].name << " : " << pairs[i].value << " } " << std::endl;
}
}
void removePair() {
pairs.pop_back();
}
private:
int counter;
std::vector<Pair> pairs;
};
But when I tried addPair() then printPairs() then removePair() it works fine. Why doesn't it throw an error saying invalid access to memory location?
You said:
from my understanding if a variable goes out of scope then it is destroyed and its memory is reallocated.
That is correct. "reallocated" is not correct word I would use. I would phrase that as: The memory used by the object is available to be used by other objects.
And then you asked:
If I have a class and it's method creates a variable, shouldn't that variable be destroyed after the method call?
That is correct.
However, your situation is different.
When you use:
pairs.push_back(x);
a copy of x is placed in pairs. The copy continues to live in pairs after the function returns. Hence, printPairs() and removePair() work just fine.
First, access to variables out of scope is undefined behavior. The program might throw an error but it might even work well. So there's no guarantee an error will be raised.
Second, std::vector::push_back makes a copy of its arguments. So nothing to worry about when passing local variables to it.

Class scope using "new"

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;
}
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.
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
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();

function calling within a class C++

Within the same class I have
Executive::Executive(std::istream& fin){
std::ifstream dFin(argv[2]);
if(!dFin.is_open()){
std::cout <<"Could not open directives file.";
std::cout <<endl;
}
else{
std::string directive;
dFin >>directive;
int x;
dFin >>x;
if(directive=="print"){
}
and the function
void Executive::print(int i) const{
if(i>MAX_NUM_POLYNOMIALS){
std::cout <<"Sorry, " <<i <<" is not within the known polynomials.";
std::cout <<endl;
}
else{
pNom[i].print(std::cout);
std::cout << i <<'\n';
}
}
In the last bit of the first code, how do I call the print function from the second code? They're in the same class, and I don't want to confuse calling it with the print function being called from another class in the second part.
In short, there is no problem in calling the print method directly in here. There are some scenarios below though for consideration.
If you have a print method in a different class, you would simply use myAnotherClass.print(...).
If you need to call a print method explicitly from the base class, you can use the base class scope explicitly as presented in the example at the bottom, such as MyBaseClass::print(...)
It is a simple case when you cannot have any clash except if you have a print method in the global scope or a namespace being used.
If it is in the global area, you would call it with ::print(...), and if it is in a namespace, you could use myNamespace::print(...)
Try to avoid "this->" at all costs, and leave that as the last resort. If you had a 'print' argumnt in the method where you are calling print, that could be one case if you could not change the argument name otherwise for some reason.
Finally, after the theoretical lesson, here goes the practical example:
Executive::Executive(std::istream& fin){
std::ifstream dFin(argv[2]);
if(!dFin.is_open()){
std::cout <<"Could not open directives file.";
std::cout <<endl;
}
else{
std::string directive;
dFin >>directive;
int x;
dFin >>x;
if(directive=="print") {
print(x); // calling the method of the current class
MyBaseClass::print(x); // calling the method of the base class
myAnotherClass.print(x); // classing the method of a different class
::print(x); // calling print in the global scope
myNamespace::print(x); // calling the method in a dedicated namespace
}
If you want to be ABSOLUTELY sure you're calling your own function you can use the this keyword if it's not a static function or the class name if it is static.
this->print(...); or Executive::print(...);
You can just fully qualify the member function to call:
Executive::Executive(std::istream& fin)
{
// ...
if(directive == "print")
{
Executive::print(x);
}
// ...
}
I should note that if you're adding a non-static print method to another different class there is no chance of a name collision here. That's because to actually call that method from outside of its containing class you have to refer to some instance to call it with.