Suppose I have a class Foo which has a member variable of type std::vector<Bar>:
class Foo;
class Bar
{
public:
int x;
Foo* parent;
void trigger(size_t i);
};
class Foo
{
public:
std::vector<Bar> arr;
void moveBack(size_t i);
};
void Bar::trigger(size_t i)
{
parent->moveBack(i);
}
void Foo::moveBack(size_t i)
{
std::swap(arr[i], arr[arr.size()-1]);
}
int main()
{
//...Init foo of type Foo and fill the arr
foo.arr[3].trigger(3);
}
I am wondering if the code above is dangerous or undefined behaviour. Essentially the object of type Bar is moving itself.
Edit: Added forward declaration
Related
I want to pass function of one object to another function as an argument. Below code is only for indication of the problem, (not realistic code). How can function IdNeeded can take function getNextId of class Bar?
class Foo
{
public:
void IdNeeded(getNextId);
}
class Bar
{
public:
int getNextId()
{
return ++id;
}
private:
int id = 0;
}
int main()
{
Bar bar;
Foo foo;
foo.IdNeeded(bar.getNextId); // foo will get id = 1
Foo anotherFoo;
anotherFoo.IdNeeded(bar.getNextId); // anotherFoo will get id = 2, because "id" is already incremented by one for foo object
}
I tried to use std::function, function pointer, std::bind, but unfortunately could not reach a final solution.
Provide a proper call back definition, and use a lambda to pack your object Foo:
#include <functional>
class Foo
{
public:
void IdNeeded(std::function<int()> f){ f();}
};
class Bar
{
public:
int getNextId()
{
return ++id;
}
private:
int id = 0;
};
int main()
{
Bar bar;
Foo foo;
foo.IdNeeded([&](){return bar.getNextId();}); // foo will get id = 1
}
In the incorrect code below of a queue, I'm trying to make the struct 'bar' hold an array of length ARR_SIZE. I want this variable to be dependent on the parameter I give it during it's construction.
So in one instance when I construct a foo I would like the array within the struct to be a length of 8 or in another case I would like to make it an array of 1000. How can this be done?
I know that you can make ARR_SIZE a static variable, but wouldn't that mean the size of the array is the same for every instance of the class foo?
Is there a way to make this parameter different for each instance of foo?
class foo
{
private:
int ARR_SIZE;
public:
foo();
foo(int arr_size);
~foo();
struct bar {
int arrInt[ARR_SIZE];
bar* next;
};
void enqueue(int a);
int dequeue();
};
foo::foo()
{
ARR_SIZE = 8;
}
foo::foo(int arr_size)
{
ARR_SIZE = arr_size;
}
Raw arrays cannot change their size at runtime in C++. That's what the std::vector class was made for in the c++ standrd library.
Change your class to
class foo
{
public:
foo() : arr_size_(8) {}
foo(size_t arr_size) : arr_size_(arr_size) {}
~foo();
struct bar {
std::vector<int> arrInt; // <<< use std::vector
bar* next;
};
void enqueue(int a);
int dequeue();
private:
size_t arr_size_;
};
Now whenever you need to instantiate a new bar object you can write
void foo::enqueue(int a) {
bar b{ arrInt(arr_size_), nullptr };
// or
bar* b = new bar{ arrInt(arr_size_), nullptr };
// ...
}
I am super-new to classes and still wrapping my brain around how they work. Any help/advice/pointers-> are appreciated!
I have two classes. Within the second class is an array of the first class. I am trying to assign values to the private member variables contained in the array of the first class.
I get this error message when compiling:
hw2Test.cpp: In member function 'void bar::set(int)':
hw2Test.cpp:11:7: error: 'int foo::x' is private
int x;
^
hw2Test.cpp:34:12: error: within this context
foodoo[0].x = x;
^
Here is the code:
#include <iostream>
using namespace std;
class foo
{
public:
private:
int x;
};
class bar
{
public:
void set(int x);
private:
foo foodoo[1];
};
int main()
{
bar tar;
tar.set(1);
return 0;
}
void bar::set(int x)
{
foodoo[0].x = x;
}
foo::x is declared as private, so only methods of foo can access it. But you are trying to access x inside of a method of bar instead, which does not have access to foo's private members.
To give bar access, you need to either:
declare foo::x as public:
class foo
{
public:
int x;
};
void bar::set(int x)
{
foodoo[0].x = x;
}
declare a public setter:
class foo
{
public:
void set(int i);
private:
int x;
};
void foo::set(int i)
{
foodoo[0].x = i;
}
void bar::set(int x)
{
foodoo[0].set(x);
}
declare bar as a friend of foo:
class foo
{
public:
private:
int x;
friend class bar;
};
void bar::set(int x)
{
foodoo[0].x = x;
}
I have a problem with a pointer defined in an nested class 'Outer::Inner' to a member function of the 'Outer' class:
class Outer{
//class Inner;
class Inner{
public:
Inner(Outer& o){
}
int (Outer::*pf)(int);
};
public:
Outer();
~Outer();
int function(int a);
Inner* i;
};
Outer::Outer(){
i = new Inner( *this );
i->pf= &Outer::function;
(i->*pf)(2); //problem here!
};
Outer::~Outer(){
delete i;
};
int Outer::function(int a){
return 0;
};
As you can see I would like to call the function through the pointer of the Inner class but I get an error: 'pf' was not declared in this scope.
As the error says, pf is not declared in that scope. It's a member of i, accessible as i->pf. Presumably, you want to call it on this:
(this->*(i->pf))(2);
You need to call the function "on" some Outer object, as it's a pointer to a member function.
Looking at your code, maybe you need this
//-----------------vvv <- argument
(this->*(i->pf))(2);
//-^--------------^ <- these are important and they say something like
// "execute function `*(i->pf)` on `this` object"
2 solutions.
1: (pointer to non-member function)
class Outer{
class Inner{
public:
Inner(Outer& o){
}
int (*pf)(int);
};
public:
Outer();
~Outer();
static int function(int a);
Inner* i;
};
Outer::Outer(){
i = new Inner( *this );
i->pf= &Outer::function;
int j = (*(i->pf))(2); // now OK
};
2: (pointer to member function, has to be called on some instance's)
class Outer{
class Inner{
public:
Inner(Outer& o){
}
int (Outer::*pf)(int);
};
public:
Outer();
~Outer();
int function(int a);
Inner* i;
};
Outer::Outer(){
i = new Inner( *this );
i->pf= &Outer::function;
int j = (this->*(i->pf))(2); // now OK
};
my question is as follows: Suppose I have:
class Foo
{
public:
Foo() {}
void setInt(int i) { myInt = i; }
int getInt() { return myInt; }
private:
int myInt;
};
class Bar
{
public:
Bar(Foo f) { /* do something with f.getInt() */ }
};
Now I have another class that has Bar as a member vairable:
class BarUser
{
public:
BarUser();
private:
Bar bar;
};
I want to write BarUser's constructor, however I want to initialize Bar with a Foo member that has 3 as its integer. I.e.:
Foo f;
f.setInt(3);
Bar b(f);
However since I have Bar as a class member, I cannot write all this code in the initialization list... What I mean is:
BarUser::BarUser() : bar(/* Foo after executing f.setInt(3) */)
{ ... }
Suppose assignment operator is not allowed for Bar - how can I initialize it as intended?
Thanks!
If you can't change Foo, write a function:
Foo make_foo(int i) {
Foo f;
f.setInt(i);
return f;
}
then initialize with bar(make_foo(3)).
You've sort of shot yourself in the foot by giving Foo a constructor but no int constructor. You might be better off adding an explicit constructor to Foo that takes an int.