C++ class variables

Started by
11 comments, last by Adehm 7 years, 4 months ago

I'm new to C++ and a bit confused on how to use public variables.

I create a class:


class board{
    public:
    int n = 0;
};

Then I manipulate it in main:


int main() {
    board xy;
    xy.n = 10;
    cout << anotherFunction();
    return 0;
}

It would seem that only in main does n = 10; What I want to do is update it in the class so another function can use it. Is that possible? And if so how can I accomplish that?


int anotherFunction(){
    board xy;
    return xy.n; //need it to equal 10 now not 0 sense main updated it 
}

Hope this makes sense. Thanks.

Advertisement

Those are two separate board objects. If you want a variable that has the same value for all objects uses a static member variable. If you want to anotherFunction() to see the original object pass the original object as a pointer or reference to anotherFunction().

Is there a way I can have a place that holds variables that all my functions can share and change?

Is there a way I can have a place that holds variables that all my functions can share and change?

Have a look at the singleton design pattern.

I can do it with global variables.


namespace ObjectGlobalVars {
   //Put all of your global variables here
     int n = 0;
}
using namespace std;
int anotherFunction(){
return ObjectGlobalVars::n;
}
int main() {
ObjectGlobalVars::n = 10;
cout << anotherFunction();
return 0;
}

Be aware that globals are generally considered bad.

They can be accessed and changed from everywhere, meaning that if there's ever a bug with a global value, it might be very hard to track down.

It's also hard to reason about code flow -- what variables does this function/class need or affect?

I would echo SiCrane's advice with pointers or references.

Hello to all my stalkers.

Problem with pointers or references as I understand it; is passing a multi dimensional variable. From what I understand is I can't pass that all through one variable, though I could be wrong. I was working on this: http://www.hackerrank.com/challenges/battleship1p and just wanted to be able to call functions to return a bool based on other data. Then instead of returning two pieces of data, which I don't know how to do, I could just set global variables from that function. Here is what I did to solve this problem; though I got a bad score because I don't know a better way of searching the board besides sequential until I find a target.


#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
namespace board {
   //Put all of your global variables here
     int n = 0;
    int xy[10][10]; //integer data repersenting board 0 = miss or dead/1 = undiscovered/2 = hit 
    int hX = 0;
    int hY = 0;
}
using namespace std;
//-------------------------------------------------------------------------------------------------------
bool hit(int x, int y){
            //search for another hit/ y-1,y+1,x-1,x+1
    if(y - 1 > -1 && board::xy[x][y-1] == 2){ //found
            board::hX = x;
            board::hY = y-1;
            return true;
    }else if(y + 1 < board::n && board::xy[x][y+1] == 2){ //found
            board::hX = x;
            board::hY = y+1;
            return true;
    }else if(x - 1 > -1 && board::xy[x-1][y] == 2){ //found
            board::hX = x-1;
            board::hY = y;
            return true;
    }else if(x + 1 < board::n && board::xy[x+1][y] == 2){ //found
            board::hX = x+1;
            board::hY = y;
            return true;
    }
    return false;
}
//-------------------------------------------------------------------------------------------------------
bool attack(int x, int y){
            //search for another hit/ y-1,y+1,x-1,x+1
    if(y - 1 > -1 && board::xy[x][y-1] == 1){ //found
            board::hX = x;
            board::hY = y-1;
            return true;
    }else if(y + 1 < board::n && board::xy[x][y+1] == 1){ //found
            board::hX = x;
            board::hY = y+1;
            return true;
    }else if(x - 1 > -1 && board::xy[x-1][y] == 1){ //found
            board::hX = x-1;
            board::hY = y;
            return true;
    }else if(x + 1 < board::n && board::xy[x+1][y] == 1){ //found
            board::hX = x+1;
            board::hY = y;
            return true;
    }
    return false;
}
//-------------------------------------------------------------------------------------------------------
int main() {
    cin >> board::n;  
    string col;
    int hX = -1;
    int hY = -1;
    for(int y = 0;y<board::n;y++){
        cin >> col;
        int x  = 0;
        for(char& c : col) {
            switch(c){    
                case 'm' || 'd':
                    board::xy[x][y] = 0;
                    break;
                case '-':
                    board::xy[x][y] = 1;
                    break;
                case 'h':
                    board::xy[x][y] = 2;
                    //store hit
                    hX = x;
                    hY = y;
                    break;
            }
            x=x+1;
        }
    }
    //board now stored in xy
    //if hX a positive number then search around it
    if(hX > -1){
        //search for another hit
        if(hit(hX,hY)){ //another hit found
            int dirX = 0;
            int dirY = 0;
            //direction known from hX - xy.hX or similier
            //find direction
            //cerr << hX << " <> " << board::hX << endl;
            if(hX > board::hX){ //x-1
                dirX = -1;
            }else if(hX < board::hX){ //x+1
                dirX = 1;
            }else if(hY < board::hY){ //y-1
                dirY = -1;    
            }else if(hY > board::hY){ //y+1
                dirY = 1;   
            }
            //check direction until = 1
            for(int i = 1;i<5;i++){
                if(board::xy[hX+dirX*i][hY+dirY*i] == 1){ //found next attack
                    hX = hX+dirX*i;
                    hY = hY+dirY*i;
                    break;                
                } 
            }
            
        }else{ //try around it until hit
            if(attack(hX,hY)){
                hX = board::hX;
                hY = board::hY;
            }
        }      
    }else{ //find a 1 to attack
        for(int y = 0;y<board::n;y++){
            for(int x = 0;x<board::n;x++){
                if(board::xy[x][y] == 1){ //attack
                    cout << y << " " << x;
                    return 0;
                }
            }
        }
    }
    cout << hY << " " << hX;
    return 0;
}

Scope- A block that holds a "context" of variables and code.

{

// First scope

{

// Second scope

}

// Second cope is gone, returning to first scope.

}

Secondly, The two objects in main and in your functions refer to other ISNTANCES of the class board.

board xy; //is an instance of board.

You can refer to the same instance by using a reference or a pointer (which gives you the original location of your instance).

int func(board* xy)

{ xy->n=10;}

board xy;

func(&xy); // You pass the LOCATION of xy and not the instance. It copies the memory address instead of the value itself.

if(xy.n==10)

{ cout << "I did it"<<endl; }

Is there a way I can have a place that holds variables that all my functions can share and change?

Have a look at the singleton design pattern.

Or don't and actually design your program.

First up, singleton is the wrong solution, pretty much every time.

Second, it's particularly not applicable here since he's looking for a global. Singletons != "OO globlals"

Do what @SiCrane suggested and pass the board to anotherFunction.
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight

constexpr int HEIGHT = 10;
constexpr int WIDTH = 10;
 
struct board {
  int tiles[HEIGHT][WIDTH];
};
 
bool hit(board const& b, int x, int y) {
  if (b.tiles[y][x] == 2)
    // etc. etc. etc.
}

You can pass a struct or class by reference to a function. The reference lets you modify the object you've passed in, unless it's const.

For returning more complex data you can also return a struct (*not* by reference!):

struct result {
  int something;
  int another;
};
 
result myfunc(int stuff) {
  return {1, 2};
}

It is very highly recommended that you get in the habit of working with these kinds of patterns: return by value rather than modifying a non-const reference parameter and _definitely_ stay out of the habit of using globals (using them would automatically fail any first-year assignment at my alma mater - and your battleships example is a first-semester-level project). You _really_ don't need them unless you're doing something special and weird, and as "easy" as they look they will _very quickly_ cause more problems than they solve.

Sean Middleditch – Game Systems Engineer – Join my team!

This topic is closed to new replies.

Advertisement