Declare default parameter circular reference without pointers? - c++

Is there any way to declare these classes in a header file without indirection?
// Forwards declaration of B
class B;
class A
{
public:
// Default parameter referring to B. May return its parameter
const B& func(const B& b = B());
};
class B
{
public:
// B ctors
B() {}
B(const B&) {}
// B has A as a member
A a;
};
Visual C++ 2008 tells me with this:
error C2514: 'B' : class has no constructors
and points to the forward declaration of B ("class B;") and obviously can't see B's constructors below. A can't follow B because B contains A as a member.
If indirection must be used, what's the best way? Perhaps in C++0x B's A could be a unique_ptr member? Or maybe there's a boost class purely to sidestep this issue?

Instead of a default parameter declare two overloads, one that takes a B by reference and one that takes no parameter. In the one that takes no parameter, call the other with B(), which will work because that method can be defined after B is defined.
...
void func();
void func(const B& b);
};
class B...
void A::func() { func(B()); }
void A::func(const B&) { }
Update:
func() returns a const B&...
That's probably not a good idea. With that definition, something like:
const B& foo = a.func();
foo.bar();
would cause the dreaded "undefined behavior" (i.e., crash) because the B to which you have a reference will be destroyed as soon as the first statement is complete. Returning things other than class members by reference is usually a bad idea.
If you really want to do this, then I think you're stuck with forcing the caller to explicitly pass in B(), that is have no default parameter.
a.func(B()).bar();
(This is the only way to avoid undefined behavior with such a function.)
Of course you could just return a copy instead of a reference, but I presume you have a reason for not doing that.
Depending on what you're doing you may be able to set up better semantics using a smart pointer like shared_ptr instead of references so that you can effectively ignore the lifetimes of the objects. You then have to start being careful of reference cycles instead, however.
I can't tell what you're trying to use this for, but you might want to have a look at some Design Patterns to see if there is an established best-practice for it. You may find that this little problem is a symptom of an unfortunate choice of class structure or containment.

Related

Object vs Reference for class members and dependency injection

I'm new to C++, with a C# background. I'm trying to use dependency injection commonly used in C# in C++ and I'm confused about the different ways to declare dependencies and pass them in and why I would use one over the other. Let's assume A depends on B.
Approach #1 - declare as object and take object
class A
{
private:
B _b;
public:
A(B b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
Approach #2 - declare as object and take reference
class A
{
private:
B _b;
public:
A(B &b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
Approach #3 - declare as reference and take object - scratch this - undefined behavior
class A
{
private:
B &_b;
public:
A(B b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
Approach #4 - declare as reference and take reference
class A
{
private:
B &_b;
public:
A(B &b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
I've tried all of the above and they all seem to work. Is there any difference between them? and if so why should I choose one over the other? my preference is #1 because I find it the most familiar and intuitive.
I've found a similar discussion discussion here but that's more about Pointers vs References.
One of the main difference between C# and C++ in this regard is that in C# classes are reference types whereas in C++ they are value types.
Approach 1 and 2 are based on copy construction. This could work if the object passed to the constructor is exactly a B. But it might fails due to object slicing if you'd use a derived class of B. Approach 2 might also fail if the source object is a constant.
Approach 3: no longer considered (scratched in your question)
Approach 4: is ok, provided the object passed by reference continues to exist as long as the object. However if function B::Bar() is not a virtual function, B::Bar() would always be called in Foo(), even if you'd use a class derived from B with its own implementation of Bar().
Approach 5: use a smart pointer and clone the object passed by reference (either with a clone() member, or by using templated constructor):
class A
{
private:
unique_ptr<B> _b;
public:
template<class T>A(const T&b): _b(make_unique<T>(b)) { }
void Foo()
{
_b->Bar();
}
};
Online demo
In your case I'd say that best solution from all mentioned is taking and storing reference. The whole point of dependency injection is using pure virtual interface without even knowing how something is implemented. It means that underneath you want vtable lookup that will execute whatever implementation is for object that is referenced. This way you can expect reference for Animal where callers will provide Elephant or Cat implementation of Animal. Moreover, if you use pure virtual interface (with at least one pure virtual function inside) you can't even pass object by value because you can't create object of pure virtual type.
As far as I remmember, C# similarly to Java distinguishes objects from builtin types and objects are passed by reference by default. In C/C++ you explicitly pass everything the way you want, so in your cases you have:
Copy of temporary copy of B You make more copies than you need. If your object is big, it will cause performance loss.
Copy of B If you simply want to store copy of some object it seems to be better way but you created not needed limitation here. If you make copy of an object, you won't modify original object. By passing it by non-const reference you create this limitation and you can't take const objects because of that. If you simply want to take some object by reference and store copy of it, most of the time you want const reference. Exceptions might be in case of noncopyable objects.
reference to temporary copy of B (invalid)
Reference to B Is completely different story. Here you don't store copy of an object but point to original one, so every change you make on this object will be visible to anyone else that has access to object you received. That's more or less how objects work by default in languages like Java. Moreover, you can use virtualization as I mentioned before. The only drawback is that you have to ensure that this object exists as long as you are using it - you are not the owner of B. You just use that but someone has control of it's existence.
As you can see, in first case Second case creates some not needed limitation. You create copy of non-const

Is it possible to use an rvalue reference as pimpl handle?

I want to create a class with a Pimpl (Private implementation). Normally you would do:
class A
{
private:
class B;
B* _pimpl = nullptr;
}
and then I would define it in the .cpp file. But I have to use dynamic allocation. Would it be possible to use an rvalue reference instead?
class A
{
public:
A(); //Constructor to init rvalue reference
private:
class B;
B&& _pimpl;
}
And then in the .cpp file:
class A::B
{
public:
int C = 3u;
}
//and then the constructor of A:
A::A() : _pimpl(B()) { } //now we should have a fresh b pimpl?
I'm currently on holidays and I only have my C++ book for reference. I read about rvalue references and thought it might work. What do you guys think?
If by "work" you mean "compile", then sure.
But _pimpl(B()) is going to initialize _pimpl as a reference to a temporary. Member references don't extend lifetime, so this construct dangles almost immediately. Therefore no, it won't work.
A unique_ptr<B> is the better type to hold a pimpl (as a default choice). The need for dynamic allocation cannot generally be avoided. But the drawbacks may be mitigated if one chooses a good custom allocator.

C++: Avoid nullptr initialization of members in constructor

A class like
class A{
public:
const B& instanceOfB ;
A(const B& someInstanceOfB):
instanceOfB(someInstanceOfB)
{
};
// some methods depending on instanceOfB here
};
should be extended to provide also some methods which do not depend on instanceOfB, and these methods must be accessible without any instanceOfB (i.e., no instance of B may exist at all).
Hence, a straight forward extension could look like
class A{
public:
B* const instanceOfB ;
A():
instanceOfB(nullptr)
{
}
// some methods not depending on instanceOfB here
void assignInstanceOfB(B* const someInstanceOfB){
instanceOfB = someInstanceOfB;};
// some methods depending on instanceOfB here
};
However, in my opinion, this has several disadvantages:
The original version of the class was easy to use, while for the extended version it must be ensured that assignInstanceOfB is called prior to any other method depending on instanceOfB
Basically, any method depending on instanceOfB must check if the initialization was perfomed. This produces a huge (i.e., ugly) overhead.
A nullptr initialization is used, which seems to be bad practice in my opinion. I generally try to avoid any pointers.
So i am not really satisfied by this design. What could look a more sophisticated version look like? Thank you!
Edit: Due to the comments, i add following additional requirements:
- Splitting of the class is not possible
- The reference to B must be stored, it is not possible to hand it only to the respective methods.
To summarize, it seems that using pointers (including smart pointers) is the recommended or at least usual way.
To address your first concern about having to call the initialize function before the object can be used, you could implement two constuctors. One would take in a pointer to B and the other defaults to nulling the pointer.
class A{
public:
B* const instanceOfB ;
A(B* const b) : instanceOfB(b) { }
A() : A(nullptr) { }
};
In regards to your third concern, using non-owning pointers is the usual way to store a reference to an object that may or may not exist. If you are hell-bent on not using pointers you could use std::optional in a manner such as this:
class A
{
public:
std::optional<std::reference_wrapper<B>> instanceOfB;
A(B * const b = nullptr) : instanceOfB(std::nullopt)
{
if (b != nullptr)
{
instanceOfB = std::make_optional(std::ref(*b));
}
}
void doSomething()
{
if (!instanceOfB)
{
return;
}
instanceOfB->get().something();
}
};
You need to use std::reference_wrapper since std::optional explicitly does not support storing references directly. You'll still need to check if the optional contains anything before using it, so you still end up needing code that's very similar to checking for a null pointer. There's even worse syntax to access the inner reference, as can be seen in doSomething(). In the end this doesn't seem like it gains you anything, and I wouldn't recommend it.

Check if std::move is done on container

Is there any way I can check is std::move done on some STL container?
I have two types of classes (lets say A and B), they keep (some) instances of another class in their internal container. If instance of A keeps instance of B in it's container, that instance of B have to keep the same instance of A in it's container, too.
A can see B's private methods (B has it as it's friend), but I have to implement move constructor on B. As B can see both's internal container, I've implemented B does all adding and removing for both classes.
Problem is:
I have to implement move constructor for A, and use stl::move on that container. After container is moved to new instance of an A, only way to notify B of detachment of old class is through the method that uses B's, and old A's container and does removing for both of classes.
Is there any way for B to know that old A's container is moved and it shouldn't acces it?
It works without checking, but as class doesn't have defined state after std::move, I shouldn't call ::remove() on it (professor says it's an error).
Please note: this is my homework problem, so I wouldn't like to get illegal help of solving complete problem, only the part of checking of object's consistency to skip calling it's functions after moving it.
EDIT: added example.
IMPORTANT:
1) I'm required to use std::move. I already know an easy way to do everything in while-loop using iterators. But, std::move is explicitly required.
2) This snippet is for understanding my problem. As student, I'd like to solve it by myself, I only need info how to skip doing one line when it is not allowed.
class A;
class B {
public:
// ...... some constructors, functions and destructor.
void add(A *a) {
// .. adds to both containers.
};
void remove(A *a) { // I need to remove from both containers at most of the times
a_container.erase(a);
a->b_container.erase(this); // PROBLEM(!!): after doing std::move(b_container) I shouldn't do this! How to check is b_container moved?
};
private:
std::_______<A*> a_container; //type of container is not important
};
class A {
friend class B;
public:
// ...... some constructors, functions and destructor.
A(A && a) :
b_container(std::move(a.b_container)) {
//..
for (B *b : b_container) {
b->add(this); //adds to B's connected to the old instance
a.remove(*b); //I need somehow to disconect old B's from pointer of moved A.
}
};
void add(B & b) {
b.add(this);
};
void remove(B & b) {
b.remove(this);
};
private:
std::_______<B*> b_container; //type of container is not important
//...
};
Is there any way I can check is std::move done on some STL container?
The std::move template does not move anything, it is only
obtains an rvalue reference to its argument and converts it to an
xvalue.
If the code similar to b_container(std::move(a.b_container)) is compiled then the std::move "works" and the b_container has a move constructor and the move constructor moves internals of the object specified as the parameter. Otherwise code is not compilable. The following example is not compilable due to missing move constructor. Here it is on coliru.
#include <utility>
class B {
public:
B() = default;
B(B &&) = delete;
};
int main() {
B b0;
B b1(std::move(b0));
return 0;
}
Summarizing above text. std::move "works" always.
The state of a moved object is unspecified. Link#00 and Link#01 explain this behavior.
Is there any way for B to know that old A's container is moved and it shouldn't access it?
There is no way to check either the old container is moved or not, i.e. to check it is state. But it is possible to access it, for instance, to call the std::vector::empty method, because the object is valid. See this link for explanations.

C++ constructor initialization reference assignment

I am sure this question has been asked before. But I cannot seem to find the exact answer that I am looking for. Basically I am trying to create an object of the class as a member of the other class and pass one of the members by reference to the owned object through the constructor. Sometimes this seems to work, other times I get a random value.
I think that I am not understanding some rudimentary rule of initialization order
Here is the code example:
class Foo
{
public:
Foo();
private:
int b;
Bar c;
};
class Bar
{
public:
Bar(int& parm);
private:
int& b_ref;
};
Foo::Foo(): b(0), c(b)
{}
Bar::Bar(int& parm): b_ref(parm)
{}
What I want is for c to own a reference to b and be able see the value as it changes.
Should I not use the initialization list in this case?
The rule is that objects are initialised in the order of their declaration in the class. In this case, it means that b is initialised before c, so this code should always work correctly.
If you swapped the order of the b and c members, then the int referenced by param would not yet be initialised in the constructor of Bar.