I have a class called woodyard. Inside there is a method called collect_wood. It's parameter is a Player object. The method adds 1 to player.wood_resource each time it is called.
I use it in main like this:
for(int i = 0; i < woodyards.size(); i++)
{
woodyards[i].collect_wood(p1);
}
p1 is a player object.
This is the collect_wood method:
void woodyard::collect_wood(Player player)
{
player.wood_resource++;
}
There is no effect on wood_resource when I run it.
Please help. I'm coding in C++ using CodeBlocks
You should use reference here.
void woodyard::collect_wood(Player& player)
{
player.wood_resource++;
}
since in your case - you increment wood_resource of copy.
Do it as Call By Reference. What your code does, it creates new Player each time instead of modifying old one.
void woodyard::collect_wood(Player& player)
{
player.wood_resource++;
}
Note & in void woodyard::collect_wood(Player& player)
You can read more about Function call by reference here
By default the functions are call by value (exceptions are there). If you need to change the original copy and not the temporary object you need to use references or pointers.
You any of the two functions:
void woodyard::collect_wood(Player& player)
{
player.wood_resource++;
}
OR
void woodyard::collect_wood(Player *player)
{
if(player)
{
*player.wood_resource++;
}
}
Related
cliques is my class object. All my class commands work when I use them in my main but for some reason I cannot make changes to my heaps or stacks through my functions. I tried using reference markers on my function parameters but still I'm having ussues. Maybe I've done the reference incorrectly. Does anyone have any ideas what I might be doing wrong?
This is one of my functions:
void UpdateTopK(cliques C, vector<cliques> minheap) {
if (C.getclique_size() < CliqueSize) {
return;
}
else if (minheap.size() < Solutions) {
minheap.push_back(C);
push_heap(minheap.begin(), minheap.end(), min_iterator());
}
else if (minheap.size() == Solutions and C.getMaxclique_prob() > minheap.front().getMaxclique_prob()) {
pop_heap(minheap.begin(), minheap.end(), min_iterator());
minheap.pop_back();
minheap.push_back(C);
push_heap(minheap.begin(), minheap.end(), min_iterator());
}
This is part of my main:
stack <cliques> cstack;
vector<cliques> max_heap;
make_heap(max_heap.begin(), max_heap.end(), max_iterator());
vector<cliques> min_heap;
make_heap(min_heap.begin(), min_heap.end(), min_iterator());
for (int i = 0; i < 5; i++) {
cliques temp(i);
cstack.push(temp);
}
while (!cstack.empty()) {
cliques temp = cstack.top();
cstack.pop();
bool pruned = GenerateChildren(temp, min_heap, max_heap, cstack, graph);
if (!pruned) {
UpdateTopK(temp, min_heap);
}
}
You are passing arguments by value, this implies that parameters are copied before being passed to the function.
So every modification inside a method refers to the local copy only. Try passing values by references, eg:
void UpdateTopK(cliques& C, vector<cliques>& minheap)
^ ^
Mind that an object that needs to be passed to a function without copy and without being edited should be passed by const T& to specify this.
I have a functional object that I'm using as body for multifunction_node:
class module
{
private:
bool valid;
QString description;
bool hasDetectionBranch;
tDataDescription bufData;
void* dllObject; //<-- This is a pointer to an object constructed with help of the external dll
qint64 TimeOut;
public:
module(const QString& _ExtLibName);
virtual ~module();
void operator() (pTransmitData _transmitData, multi_node::output_ports_type &op);
};
'dllObject' is created at construction time of the object 'module':
module::module(const QString& _ExtLibName) :
valid(true), hasDetectionBranch(false)
{
GetObjectDescription = (tGetObjectDescription)QLibrary::resolve(_ExtLibName, "GetObjectDescription");
CreateObject = (tCreateObject)QLibrary::resolve(_ExtLibName, "CreateObject");
DestroyObject = (tDestroyObject)QLibrary::resolve(_ExtLibName, "DestroyObject");
if (!CreateObject || !DestroyObject || !GetObjectDescription)
valid = false;
else
{
description = QString(GetObjectDescription());
dllObject = CreateObject();
}
}
And this is when 'dllObject' is destroyed:
module::~module()
{
if (valid)
{
DestroyObject(dllObject);
}
}
I've built a little graph:
void MainWindow::goBabyClicked(void)
{
module mod(QString("my.dll")); //<-- Here is OK and mod.dllObject is correct
if (!mod.isValid())
{
qDebug() << "mod is invalid!\n";
return;
}
first fir(input);
folder fol(QString("C:/out"), 10000);
graph g;
source_node<pTransmitData> src(g, fir, false);
multi_node mnode(g, tbb::flow::serial, mod); //<-- WTF? ~module() is executed!
function_node<pTransmitData> f(g, tbb::flow::serial, fol);
make_edge(src, mnode);
make_edge(mnode, f);
src.activate();
g.wait_for_all();
}
So I have 2 questions:
1) Why ~module() is executed and how to prevent this?
2) How to keep pointer for nested object correctly?
UPDATE Added some dummy code to prevent destroying dllObject at first time like:
bool b = false;
module::~module()
{
if (valid && b)
{
DestroyObject(dllObject);
}
if (!b)
b = true;
valid = false;
}
Now it works as expected but looks ugly :/
Max,
I assume you have a typedef of multi_node which is similar to the one in the reference manual example.
The constructor for the multifunction_node has the following signature:
multifunction_node( graph &g, size_t concurrency, Body body );
The body object is copied during the parameter passing and also during the construction of the node, so there are two copies of mod created during construction (actually three, as an initial copy of the body is also stored for re-initializing the body when calling reset() with rf_reset_bodies). The destructor calls you are seeing are probably those used to destroy the copies.
The body object should also have a copy-constructor defined or be able to accept the default-copy-constructor to make copies of the body. I think the QString has a copy-constructor defined, but I don't know about fields like tDataDescription. (I thought we had covered the basic requirements for Body objects in the Reference Manual, but I am still looking for the section.) In any case, the Body class must be CopyConstructible, as it is copied multiple times.
Regards,
Chris
I have some problems with understanding function pointers. Although I've read lots of topics on this I still have problems with the follow case.
My example is simple - I have a joystick class which has some function pointers as well as functions through which these pointers can be assigned and I don't know how to do this properly.
I'll try to keep it simple:
class Joystick {
void (Player::*OnShootKeyPressed)(); // pointer that takes no arguments and returns nothing
void SetCallback(void (Player::*f)) {
OnShotKeyPressed = f;
}
}
class Player {
void OnShootAction() { ...do the shooting...}
void Initialize() {
Joystick* joy = pInputMng->GetJoystick();
joy->SetCallback( &Player::OnShootAction() );
}
}
--Edited after Captain Obvlious comment--
That's one short example of what I want to achieve and I don't seem to understand these function pointers correctly. What am I doing wrong?
I appreciate all the help in advance!
I love function pointers. I consider them among my best personal friends. But this is probably not the time for them. When you have whole objects calling each other back and forth, Just pass the object.
If you need greater decoupling between the objects, build an interface. I'll go with the interface route because why not? Once you've seen the hard way, the easy way's easy.
First, define an interface for users of the joystick
class ButtonUser
{
virtual void OnShootAction() = 0; // function to be implemented by children
virtual void OnJumpAction() = 0;
virtual void OnDeathBlossomAction() = 0;
...
}
Now a joystick that uses the button interface and knows absolutely nothing about Player
class Joystick {
ButtonUser * pUser;
void SetCallback(ButtonUser * puser) {
pUser = puser;
}
void OnKeyPressed(key) {
if (pUser != NULL) {
switch( key ) {
case SHOOT:
pUser->OnShootAction();
break;
case JUMP:
pUser->OnjumpAction();
break;
case DB:
pUser->OnDeathBlossomAction();
break;
...
}
}
}
}
And Player installs itself as Joystick's user
class Player: public ButtonUser{
void OnShootAction() { ...do the shooting...}
void OnJumpAction() {...jump...};
void OnDeathBlossomAction() {...blow $#!+ up!...}
...
void Initialize() {
Joystick* joy = pInputMng->GetJoystick();
joy->SetCallback( this );
}
CORRECTED CODE & ANSWER
1.) I was having some problems with namespaces not mentioned in the question so I wasn't able to create a function.
Both classes were under the namespace so the function for assigning a function pointer was rejected:
void SetCallback(void (ehJoystick::*f)())
It was required to be this instead:
void SetCallback(void (eg::ehJoystick::*f)())
But then, compiler didn't accept the namespace infront of that. I thought I was doing something wrong elsewhere but there problem was there all the time.
2.) I didn't know you need an object reference where you want to call a member function pointer. Following code is correct and working.
class Joystick {
Player* pPlayer;
void (Player::*OnShootKeyPressed)() = NULL; // pointer that takes no arguments and returns nothing
void SetCallback(void (Player::*f)(), Player *p) {
OnShotKeyPressed = f;
pPlayer = p; // we need a reference to the object
}
void OnKeyPressed(key) {
if( key == SHOOT && OnShootKeyPressed != NULL ) {
(pPlayer->*OnShootKeyPressed)(); //that's how the function is called
}
}
class Player {
void OnShootAction() { ...do the shooting...}
void Initialize() {
Joystick* joy = pInputMng->GetJoystick();
joy->SetCallback( &Player::OnShootAction, this );
}
I have an int member named size within my blob class whose value I am attempting to change within a method. Initially, I tried...
void blob::make_union(blob parent_blob){
parent=&parent_blob;
parent_blob.size = parent_size
}
Then I tried making a function whose sole purpose was to change the size value. Its worth noting that it changes the values within the function as verified by some cout statements.
int blob::change_size(int dat_size){
size=size+dat_size;
return this.size;
}
after making the new method change my other method
'void blob::make_union(blob parent_blob){
parent=&parent_blob;
int temp = size;
parent_blob.size = parent_blob.change_size(temp);
}'
still no dice. The following within main function does work.
if (charmatrix[m-1][n-1]==charmatrix[m][n]){
blobmatrix[m][n].make_union(blobmatrix[m-1][n-1]);
blobmatrix[m-1][n-1].size=blobmatrix[m-1][n-1].size + blobmatrix[m][n].size;
What am I doing wrong?
You are passing your blob class by value: you are making a copy of your blob object, and that is what the function change_size is working with.
void increment_number(int i) { ++i; }
void increment_number_ref(int& i) { ++i; }
int main()
{
int n = 6;
// This takes a copy of the number, and increments that number, not the one passed in!
increment_number(n);
// n == 6
// This passed our object by reference. No copy is made, so the function works with the correct object.
increment_number_ref(n);
// n == 7
return 0;
}
You need to pass your blob by reference (or as a pointer) if you wish to modify that object's value: see above.
In languages that have pass by reference and pass by value - if you have a situation where you make a change, and then suddenly the change is 'gone', you're almost certainly passing a copy vs a reference.
Try changing the prototype to pass in the blob by reference.
im working in a text-based RPG game, but when I'm setting the values to X variable, when I access that propertie again, it is in its default value, am I doing something wrong?
class Game
{
private:
bool podeAndar;
bool estaBatalhando;
Jogador _jogador;
Mapa _mapa;
public:
Game() { }
Game(Jogador _j){
_jogador = Jogador(_j.getNome());
_mapa.LoadMapa();
podeAndar = true;
estaBatalhando = false;
}
~Game(void)
{
}
Jogador getJogador() {
return _jogador;
}
void setJogador(Jogador v) {
_jogador = v;
}
}
My "Player" class
#pragma once
#include "Criatura.h"
#include <string>
class Jogador :
public Criatura
{
private:
int _cap;
public:
Jogador(std::string nome)
{
setNome(nome);
setCap(150);
}
Jogador() { }
~Jogador(void)
{
}
int getCap(){
return _cap;
}
void setCap(int v){
_cap = v;
}
}
Them my "Main" - when I set the value, when I'm following it in the debugger, it sets the value correctly, but when I access the game.getJogador().getCap() again, it has the default value 150.
int _tmain(int argc, _TCHAR* argv[])
{
Jogador _player = Jogador("Kyore");
Game game = Game(_player);
while(true){
std::cout << game.getJogador().getCap(); //print 150
game.getJogador().setCap(100); //set cap to 100
std::cout << game.getJogador().getCap(); //print 150 again
break;
}
}
In Game class, change this
Jogador getJogador() {
return _jogador;
}
to
Jogador& getJogador() {
return _jogador;
}
And add one more method only to read:
const Jogador& getJogador()const {
return _jogador;
}
Update for the questions asked in the comment
To fix your specific issue of value remaining as 150 inspite of setting a new value, converting the return type to reference is enough.
Why returning reference works?
Because, whenever your original version of getJogador() is called, a copy of the object is
created. Even though you are changing its value, you are actually
changing the value of the temporary object created, not the original
one.
So as your intention is to modify the original object, we need
to access the original one, not its temporary copy. Reference is
the better mechanism in such cases (pointer being the other mechanism, but less safer than reference)
Now about why I suggested the new over load of a const member
function, returning a const reference: this is to highlight to you that it is possible to still get the object without changing its internal state unintentionally. Your sample code does not differentiate between the two getJogador() functions.
So to understand, add these two functions to your Game class:
void DontManipulate()const { std::cout<<getJogador().getCap(); }
void Manipulate() { std::cout<<getJogador().getCap(); }
See the compiler error(s) that you get: - it should throw light on the differences.
Additionally, if you std::cout some message in both the getJogador() functions, you should be able to figure out the differences.
The problem is in your getJogador() method.
In C++, objects can be passed "by value" - which is where the program (usually) copies the object's raw data into a new location, whereas in C# and Java objects are always passed by reference (not counting C#'s structs which are passed by-value similar to C++). C++ will use the "copy constructor" to perform this copy. C++ will create the copy constructor if it isn't explicitly defined in your code, the signature has the form ClassName(ClassName& other);, the default (non-explicit) copy-constructor performs a shallow, member-wise copy operation.
In your case, your getJogador method is returning a copy of your Jogador instance field's data.
Change the method to return a reference or a pointer, like so:
Jogador& getJogador() const {
return _jogador;
}
or
Jogador* getJogador() const {
return &_jogador;
}
The const modifier informs the compiler that this method is not intended to modify the state of your Game class, so the compiler might perform certain optimizations as well as prevent successful compilation if the method does attempt to modify state.