Reputation: 25
I want to get public:
member variable from another class.
But I can't get them. Would you direct me how to do it?
There is hand
variable in each class User
and Computer
.
And I want to get them at doJudge()
method's std::cout
in class Judge
, which means user.hand
and computer.hand
.
However those value says:
User CHOSE hand in class Judge := 7345888
Computer CHOSE hand in class Judge := 0
This is my code:
#include <iostream>
#include <random>
#include <ctime>
using namespace std;
int random(int low, int high)
{
return low + rand() % (high - low + 1);
}
class User
{
public :
User(){}; //constructor
int hand;
void setHand()
{
std::cout << "What you choose? (ROCK = 1, SCISSORS = 2, PAPER = 3) := ";
std::cin>> hand;
}
};
class Computer
{
public :
Computer(){}; //constructor
int hand;
void setHand()
{
hand = random(1, 3);
std::cout << "Computer choose := " << hand << std::endl;
}
};
class Judge
{
public :
User user;
Computer computer;
Judge(){}; //constructor
void doJudge()
{
std::cout << "User CHOSE hand in class Judge := " << user.hand << std::endl;
std::cout << "Computer CHOSE hand in class Judge := " << computer.hand << std::endl;
}
};
int main()
{
srand(time(NULL));
User user;
user.setHand();
Computer computer;
computer.setHand();
Judge judge;
judge.doJudge();
}
compile and execute:
C:\RPS>g++ --version
g++ (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
C:\RPS>rps.exe
What you choose? (ROCK = 1, SCISSORS = 2, PAPER = 3) := 2
Computer choose := 2
User CHOSE hand in class Judge := 7345888
Computer CHOSE hand in class Judge := 0
I have spent more than a week but I am giving up.
Please explain to me why I can not get the same values which I and the Computer chose?
Upvotes: -5
Views: 126
Reputation: 25
I appreciate you all let me know how to do it. I tried to 3 different way into 1 code, which are value, pointer and reference. Probably still I don't understand them and it's need to be correction in my code, however the compile is pass and I can see what I want to see in the console, so I am grad to it!
// g++ -o rps.exe rps.cpp
#include <iostream>
#include <random>
int random(int const low, int const high)
{
static std::mt19937 mt{ std::random_device{}() };
static std::uniform_int_distribution<int> random_number;
using param_type = std::uniform_int_distribution<int>::param_type;
return random_number(mt, param_type{ low, high });
}
class User
{
public :
User(){}; //constructor
int hand;
void setHand()
{
std::cout << "What you choose? (ROCK = 1, SCISSORS = 2, PAPER = 3) := ";
std::cin>> hand;
}
};
class Computer
{
public :
Computer(){}; //constructor
int hand;
void setHand()
{
hand = random(1, 3);
std::cout << "Computer choose := " << hand << std::endl;
}
};
class Judge_R //By Reference
{
public :
User& user_R;
Computer& computer_R;
Judge_R(User& user_R, Computer& computer_R) : user_R(user_R), computer_R(computer_R) {};
void doJudge()
{
std::cout << "User CHOSE hand in class Judge_R := " << user_R.hand << std::endl;
std::cout << "Computer CHOSE hand in class Judge_R := " << computer_R.hand << std::endl;
}
};
class Judge_P //By Pointer
{
public :
User* user_P;
Computer* computer_P;
Judge_P(User* user_P, Computer* computer_P) : user_P(user_P), computer_P(computer_P) {};
void doJudge()
{
std::cout << "User CHOSE hand in class Judge_P := " << user_P->hand << std::endl;
std::cout << "Computer CHOSE hand in class Judge_P := " << computer_P->hand << std::endl;
}
};
class Judge_V //By Value
{
public :
void doJudge(int const user_hand, int const computer_hand)
{
std::cout << "User CHOSE hand in class Judge_V := " << user_hand << std::endl;
std::cout << "Computer CHOSE hand in class Judge_V := " << computer_hand << std::endl;
}
};
int main()
{
User user;
user.setHand();
//std::cout << " user.hand in main() := " << user.hand << std::endl;
Computer computer;
computer.setHand();
//std::cout << " computer.hand in main() := " << computer.hand << std::endl;
//By Reference
Judge_R judge_R(user, computer);
judge_R.doJudge();
//By Pointer
Judge_P judge_P(&user, &computer);
judge_P.doJudge();
//By value
Judge_V judge_V;
judge_V.doJudge(user.hand, computer.hand);
}
C:\RPS>g++ -o rps.exe rps.cpp
C:\RPS>rps.exe
What you choose? (ROCK = 1, SCISSORS = 2, PAPER = 3) := 1
Computer choose := 2
User CHOSE hand in class Judge_R := 1
Computer CHOSE hand in class Judge_R := 2
User CHOSE hand in class Judge_P := 1
Computer CHOSE hand in class Judge_P := 2
User CHOSE hand in class Judge_V := 1
Computer CHOSE hand in class Judge_V := 2
Upvotes: 0
Reputation: 2206
How to get member variable from another class in C++
Suppose you have function f
, and you want function f
to be able to use variables that are defined outside of f
. There are a number of different ways to accomplish this, but the simplest is to pass the variables you want to use as arguments to function f
.
In this question, for example, function Judge::doJudge
needs to use variables that are defined as public members of classes User
and Computer
.
On the receiving end, define two parameters, user_hand
and computer_hand
, to receive the arguments.
void doJudge(int const user_hand, int const computer_hand)
{
std::cout << "User CHOSE hand in class Judge := " << user_hand << std::endl;
std::cout << "Computer CHOSE hand in class Judge := " << computer_hand << std::endl;
}
On the call side, in function main
, pass in the arguments you want to use.
int main()
{
srand(time(NULL));
User user;
user.setHand();
Computer computer;
computer.setHand();
Judge judge;
judge.doJudge(user.hand, computer.hand); // Pass in arguments
}
What you choose? (ROCK = 1, SCISSORS = 2, PAPER = 3) := 2
Computer choose := 3
User CHOSE hand in class Judge := 2
Computer CHOSE hand in class Judge := 3
This appears to be some sort of homework assignment, so I am not sure what the problem specification says about class Judge
. The problem spec may require that class Judge
be used. With the design above, however, you could eliminate class Judge
completely, and just keep function doJudge
as a stand-alone, free function.
Otherwise, you should delete the member variables user
and computer
that are defined in class Judge
, and declare member function doJudge
as const
.
As things stand now, all of the constructor functions are empty. They do nothing. If you wanted, you could erase them, which would would cause the compiler to provide compiler-supplied, default constructor functions. Those, too, would do nothing.
With those changes, class Judge
would look like this:
class Judge
{
public:
void doJudge(int const user_hand, int const computer_hand) const
{
std::cout << "User CHOSE hand in class Judge := " << user_hand << std::endl;
std::cout << "Computer CHOSE hand in class Judge := " << computer_hand << std::endl;
}
};
rand()
Considered HarmfulIn a video from 2013, Stephan T. Lavavej explains why you should avoid std::rand
: rand() Considered Harmful.
Your function random
can be replaced by the function below. It seeds the random number generator only once, on the first call to the function.
int random(int const low, int const high)
{
static std::mt19937 mt{ std::random_device{}() };
static std::uniform_int_distribution<int> random_number;
using param_type = std::uniform_int_distribution<int>::param_type;
return random_number(mt, param_type{ low, high });
}
Notes
std::mt19937
is a Mersenne Twister random number engine from header <random>
.
std::random_device
, also from header <random>
, is a system-dependent way to generate random, unsigned, 32-bit values. Depending on the system, the values can be either pseudo-random quantities or truly random quantities. It is used above to seed std::mt19937
, where the initializer is std::random_device{}()
. This instantiates a temporary object of type random_device
, and then invokes its "call" operator()
, to generate a 32-bit seed.
std::uniform_int_distribution
is a random number distribution from header <random>
. As its name suggests, it generates uniformly distributed integers using the random bits it gets from a random number engine. When instantiated with type int
, e.g. std::uniform_int_distribution<int>
, its "call" operator()
returns a random integer of type int
.
param_type
is the type used by std::uniform_int_distribution<int>
to specify the range of values from which random integers are drawn. param_type{ low, high }
is the closed interval [low, high].
When a "local" variable of a function is declared to be static
, it is allocated and initialized only once. This happens on the first invocation of the function. Once allocated, the lifetime of a static variable extends until the end of the program. It holds its value between calls to the function.
In function random_integer
(above), static variable mt
is seeded only once, during its construction, using std::random_device
.
Similarly, static variable random_number
is initialized only once, by its default constructor.
The return statement invokes the call operator of object random_number
, passing in the random number engine mt
and a param_type
object that specifies the range.
When you prefix names from the C++ Standard Library with std::
, it is not necessary to have using namespace std;
in your program. In production work, most professional programmers avoid using namesapce std;
, so you should consider eliminating it here.
// main.cpp
#include <iostream>
#include <random>
int random(int const low, int const high)
{
static std::mt19937 mt{ std::random_device{}() };
static std::uniform_int_distribution<int> random_number;
using param_type = std::uniform_int_distribution<int>::param_type;
return random_number(mt, param_type{ low, high });
}
class User
{
public:
int hand;
void setHand()
{
std::cout << "What you choose? (ROCK = 1, SCISSORS = 2, PAPER = 3) := ";
std::cin >> hand;
}
};
class Computer
{
public:
int hand;
void setHand()
{
hand = random(1, 3);
std::cout << "Computer choose := " << hand << std::endl;
}
};
class Judge
{
public:
void doJudge(int const user_hand, int const computer_hand) const
{
std::cout << "User CHOSE hand in class Judge := " << user_hand << std::endl;
std::cout << "Computer CHOSE hand in class Judge := " << computer_hand << std::endl;
}
};
int main()
{
User user;
user.setHand();
Computer computer;
computer.setHand();
Judge judge;
judge.doJudge(user.hand, computer.hand);
}
// end file: main.cpp
Upvotes: 0
Reputation: 598114
The user
and computer
variables inside of main()
are different than the user
and computer
members inside of the Judge
class. You are populating the former, but then acting on the latter.
To do what you are attempting, you should get rid of the variables inside of Judge
, and instead pass them into doJudge()
as parameters, eg:
class Judge
{
public :
Judge(){}; //constructor
void doJudge(const User &user, const Computer &computer)
{
std::cout << "User CHOSE hand in class Judge := " << user.hand << std::endl;
std::cout << "Computer CHOSE hand in class Judge := " << computer.hand << std::endl;
}
};
int main()
{
srand(time(NULL));
User user;
user.setHand();
Computer computer;
computer.setHand();
Judge judge;
judge.doJudge(user, computer);
}
Or, you should make the variables inside of Judge
point/refer to the variables inside of main()
, eg:
class Judge
{
public :
User& user;
Computer& computer;
Judge(User& user, Computer& computer) : user(user), computer(computer) {};
void doJudge()
{
std::cout << "User CHOSE hand in class Judge := " << user.hand << std::endl;
std::cout << "Computer CHOSE hand in class Judge := " << computer.hand << std::endl;
}
};
int main()
{
srand(time(NULL));
User user;
user.setHand();
Computer computer;
computer.setHand();
Judge judge(user, computer);
judge.doJudge();
}
Upvotes: 2