I have two classes, Foo and Bar. They both contain a pointer to a Baz object. I want the Baz pointers in both an instance of Foo and an Instance of Bar to point to the same Baz object.
A Baz object has a member called name with getter and setter functions.
A Foo object contains a Bar object.
A Bar object has a method to print the name of the Baz object.
The Baz objects name must be set in the scope of Foo.
This is what I have tried:
In the constructor of Foo, it sets the name of this bazA, and sets the bazB belonging to bar to be equal to the bazA belonging to Foo.
//Foo.h
class Foo {
public:
explicit Foo();
Baz* bazA;
Bar bar;
}
//Foo.cpp
Foo::Foo()
{
this->bazA->setName("hello");
this->bar.bazB = bazA;
}
//Bar.h
class Bar{
public:
Baz* bazB;
void printName ();
}
//Bar.cpp
void Bar::printName ()
{
std::cout << "name: " << bazB->getName();
//Should print out "name: hello"
}
When I do this:
//Main.cpp
Foo foo;
foo.bar.printName();
The program crashes because the name member has not been initialised in the Baz object that belongs to the Bar object.
But the Baz object belonging to Bar should be the same Baz object that belongs to Foo, which has had its name set, so it should work.
Why am I getting this error?
How can I correctly share a Baz object between the Foo and Bar classes?
The code you have to share the objects is correct: Foo creates the Baz, then passes it to the Bar. The issue is you are not constructing the Baz properly:
Foo::Foo()
{
this->bazA->setName("hello"); // crash because bazA hasn't had memory allocated
this->bar.bazB = bazA; // setting bazB to invalid memory
}
Instead, you should just have an object of Baz in Foo, and share it with Bar:
class Foo {
public:
Foo();
Baz bazA;
Bar bar;
}
Foo::Foo()
{
bazA.setName("hello");
bar.bazB = &bazA;
}
Even better, Bar's constructor should take a Baz reference instead:
class Bar
{
public:
Bar(Baz& b) : bazB(b){}
private:
Baz& bazB;
};
Foo::Foo()
: bazA(), bar(bazA)
{
bazA.setName("hello");
}
Here I assumed that Class and Public were typos and corrected them.
Related
Suppose we have a class Foo as follows:
struct Foo
{
int x = 100;
void print()
{
std::cout << x << std::endl;
}
};
Obviously we can use std::function to wrap Foo::print as follows:
std::function<void(Foo*)> f(&Foo::print);
Foo bar;
f(&bar); // Output 100
// or
std::function<void(Foo&)> f(&Foo::print);
Foo bar;
f(bar); // Output 100
But once I found that use std::function<void(Foo)> instead of std::function<void(Foo*)> or std::function<void(Foo&)> still works:
// Neither Foo& nor Foo*
std::function<void(Foo)> f(&Foo::print);
Foo bar;
f(bar); // Still output 100
Why does the last one works?
Member functions require a specific class object to invoke, and void(Foo) is just a function type that accepts a copy of the Foo class.
So f(bar) will copy bar and invoke the print() member function of its copy. If Foo is not copyable then it won't work.
I have a class Foo that references Bar:
class Foo {
Bar &bar;
};
and bar requires an int& to be constructed:
Class Bar {
Bar(int& required_int);
}
I want to be able to initialize Bar when I initalize Foo, but I cannot seem to do so using either of the following:
Foo::Foo(int &my_int) : bar(my_int) {
//...
}
Foo::Foo(int &my_int) : bar(new Bar(my_int)) {
//...
}
Because the compiler complains that whatever is inside bar(...) must be an lvalue. Is this initalization chaining possible? I don't see how bar(...) could ever contain an lvalue if my instance of Bar doesn't exist yet.
class Foo {
Bar & bar;
};
Here bar can only refer to an existing Bar object as it's a reference. You cannot initialize it yourself in Foo class. So, a valid ctor would be similar to this:
Foo::Foo(Bar & existingBar) : bar(existingBar){}
If you want Foo class to have its own independent Bar object, then remove the reference and initialize it like you're doing already.
I have a class defined as follows:
class Foo {
private:
boolean feature;
public:
Foo(boolean feature) : feature(feature) {}
// ...
};
I'm trying to construct an instance, as a private property of another class:
class Bar {
private:
Foo foo(true);
// ...
};
This doesn't work. I get expected identifier before numeric constant on the line with the declaration. When I remove the parameter from Foo's constructor definition simply and ask for a Foo foo;, it works.
Why?
How do I define and declare an instance of Foo that takes a boolean parameter?
You can't use that initialisation syntax in a class member declaration; you can only initialise members with {} or =. The following should work (assuming support for C++11 or later):
Foo foo{true};
Foo foo = Foo(true);
The pre-C++11 way to do this is:
class Bar {
public:
Bar() : foo(true){} //initialization
private:
Foo foo; //no parameter
};
Bonus:
class Bar {
private:
Foo foo(); //<- This is a function declaration for a function
//named foo that takes no parameters returning a Foo.
//There is no Foo object declared here!
};
I have a struct of Foo:
struct Foo
{
};
I have a struct of Bar:
struct Bar
{
};
They are handled by 2 more structs which maintain (add/remove) a pointer array of each:
struct FooContainer
{
Foo** FooList;
// add(), remove() etc
};
struct BarContainer
{
Bar** BarList;
// add(), remove() etc
};
Now, what I WANT is another struct called Baz which links (in a one-to-many fashion) Foo to Baz. I can't (for reasons not explained here) refer to them by index, it must be by pointer/reference.
Something like this:
struct Baz
{
Foo* foo;
Bar* bar;
};
If I wanted to add a constructor to Baz which took these non-const pointers, how would I do it?
Baz should allow me to change which instance of Foo and Bar it points to... so it's pointers don't want to be const.
Do I pass the pointers into the constructor as const and then do something with them as I would if I were passing a reference to a struct? I then get issues with trying to set the value of a non-const pointer to a const pointer.
I hope this question makes sense...
Edit: Should I use reference instead of pointer?
Baz should allow me to change which instance of Foo and Bar it points to... so it's pointers don't want to be const.
That is correct, you don't want to store constant pointers. However, it does not prevent you to store pointers to const, which is not the same thing.
This sounds confusing, so here is an illustration using your Baz example:
struct Baz
{
const Foo* foo;
const Bar* bar;
Baz(const Foo* newFoo, const Bar* newBar) : foo(newFoo), bar(newBar) {}
void setFoo(const Foo* newFoo) { foo = newFoo; }
void setBar(const Bar* newBar) { bar = newBar; }
};
everything is going to compile fine: it's Foo and Bar pointed to by foo and bar that are const, not the pointers themselves, which leaves you free to change the pointers as you wish.
This, on the other hand, is not going to compile:
struct Baz
{ // Note how const has moved to the other side of the asterisk
Foo* const foo;
Bar* const bar;
Baz(Foo* newFoo, Bar* newBar) : foo(newFoo), bar(newBar) {}
void setFoo(Foo* newFoo) { foo = newFoo; } // BROKEN!!!
void setBar(Bar* newBar) { bar = newBar; } // BROKEN!!!
};
Now the pointer, not the "pointee", is const, preventing you from changing foo or bar members.
For example, I have two classes
class Foo;
class Bar;
class Foo {
const Bar &m_bar;
...
};
class Bar {
const Foo &m_foo;
...
};
Let foo is object of Foo and bar is object of Bar. Is there any way (normal or "hacking") to create/initialize foo and bar that their members m_bar and m_foo would referenced to each other (I mean foo.m_bar is bar and bar.m_foo is 'foo')?
It is allowed to add any members to Foo and Bar, to add parents for them, to make they templates and so on.
What is the linkage of foo and bar? If they have external
linkage, you can write something like:
extern Foo foo;
extern Bar bar;
Foo foo( bar );
Bar bar( foo );
(I'm assuming here that it is the constructors which set the
reference to a parameter.)
This supposes namespace scope and static lifetime, of course
(but an anonymous namespace is fine).
If they are class members, there's no problem either:
class Together
{
Foo foo;
Bar bar;
public:
Together() : foo( bar ), bar( foo ) {}
};
If they're local variables (no binding), I don't think there's
a solution.
EDIT:
Actually, the local variables have a simple solution: just
define a local class which has them as members, and use it.
This can't work if i understand your Problem correctly, since to create an Object Bar you need Foo and vice versa.
You must not use References but an Pointer instead. Where you can create both Objects separatley and then set Bar to Foo and Foo to Bar.
class Foo
{
public:
Foo();
void setBar( const Bar* bar ){ _bar = bar; }
private:
const Bar* _bar;
}
// class Bar analog to Foo
void xxx:something(void)
{
Foo* f = new Foo;
Bar* b = nee Bar;
f->setBar(b);
b->setBar(f);
...
}