Sunday, December 2, 2012

Pointers, References and Local Variables

Well, I bring here an example when you should figure out how constructors, pointers and reference works.

Thus, here it goes:

Note: Take a fast look to A class and start reading in main function.

#include <iostream>
#include <algorithm>
#include <stdlib.h>

using namespace std;

class A{
private:
    int a;
public:
    A() : a(-1){
        cout << "Default constructor" << endl;
    }
    A(int val) : a(val){
        cout << "Calling contructor by int" << endl;
    }
    //************************************
    A(A* val){
        cout << "Calling contructor by A_pointer" << endl;
        a = val->get();
    }
    A(A& val){
        cout << "Calling contructor by A_reference" << endl;
        a = val.get();
    }

    // This can't be done because when the constructor is called
    // the parameter of the function calls itself, I mean, val is being
    // a local variable
    /*A(A val){
        a = val.get();
    }*/

    int get(){ return a; }
    int get() const { cout << "get 'a' by a const variable\n"; return a; }
    int& getRef(){ return a; }
    //int& getRef() const{ return a; } This can't be done
};


void byPointers(A *a, A *b){
    *a = b->get()*2; //(-1 * 2 = -2)
    // this can be done because a points to a instanced class A
    // in case that would point to null this would be a segmentacion fault
    // on runtime

    // Beside, this calls the constructor by value
}

void byReference(A& a, const A& b){
    a.getRef() = 1000; // we change a_int value, because a is a reference and a.getRef return the atribut inside the class by reference
                       // if the int atribut would've been public that would be equivalent to a.a = 1000;

    //so, because in this call, a and b are A_value, if we change a, also are changing b, let's look:
    cout << b.get() << endl;

    //However, we can't change the b value, because is constant although points to the same variable
}
void byReference2(A& a){
    a.getRef() = 1000000;
}

void byCopy(A a){
    cout << "a: " << a.get() << endl;

    a = A(25); 
    cout << "a: " << a.get() << endl; // now it's 25

    a.getRef() = 26;
    cout << "a: " << a.get() << endl; // now it's 26 but still being
    // a local variable
}

int main(){
    cout << "First example:" << endl;
    A A_value; // this calls default constructor
    
    cout << A_value.get() << endl;
    A* A_pointer; // this doesn't because is a pointer
    A_pointer = &A_value; // this doesn't call any A constructor
    *A_pointer = A_value; // this is equivialent to the previous line
    cout << A_pointer->get() << ", " << (*A_pointer).get() << endl << endl; // point to A_value (two ways to access it)
    //**************************************************************************************

    cout << "Second example:" << endl;
    byPointers(&A_value,&A_value); // this doesn't call any constructor
    // just points to the references of A_value, so inside the function 
    // if we change A *a, A *b pointers we'll change A_value
    cout << endl;

    // This is a bit obfuscated, so peruse
    byCopy(A_value); // byCopy expect to creat (A a) as a local variable
                     // so calls A_reference, or method to copy a class
                     // however, the construtor is by reference, a still be
                     // a local variable
    cout << A_value.get() << endl << endl;// Thus, we haven't changed any attribut of A_value
    //**************************************************************************************
    
    cout << "Third example:" << endl;
    byReference(A_value, A_value); // pass by reference doesn't call any constructor
                                   // because a and b are exactly A_value
    // So, after the call, A_value have changed:
    cout << A_value.get() << endl;

    // even, we can do the same with the pointer
    byReference2(*A_pointer);
    // and because A_pointer points to A_value, this will also change the value
    cout << A_value.get() << endl; 

    system("pause");
    return 0;
}

No comments:

Post a Comment