Reputation: 392
I would like to implement several constructors for my class via overloading. As I understand the way to do this idiomatically, following the DRY principle, is using a feature called delegating constructors. I also have seen thoughts about using reference parameters everywhere and avoiding pointers at all cost because references is a c++ way etc.
So here is how I see this could be implemented with pointers (which works):
class B {};
class C {};
class A {
public:
A();
A(const B* b);
A(const B* b, const C* c);
private:
const B* b_;
const C* c_;
};
// These ctors short and concise, delegating work to last ctor
A::A() : A(nullptr, nullptr) {}
A::A(const B* b) : A(b, nullptr) {}
// This ctor contains code that deals with b or c being nullptr
// Ideally I only modify code in this ctor (DRY)
A::A(const B* b, const C* c) : b_(b), c_(c) {
//code
}
The following, obviously, doesn't work:
class B {};
class C {};
class A {
public:
A();
A(const B& b);
A(const B& b, const C& c);
private:
const B& b_;
const C& c_;
};
A::A() : A(nullptr, nullptr) {}
A::A(const B& b) : A(b, nullptr) {}
A::A(const B& b, const C& c) : b_(b), c_(c) {
//code
}
So the question is how to implement delegating constructors following semantics in a pointer example but with reference as constructor's parameters.
(Do I totally miss the point here somewhere? Maybe even staring with the overall idea?)
Upvotes: 4
Views: 717
Reputation: 2354
You cannot pass nullptr
to a reference. It exists precisely with this purpose.
A pointer is a variable which contains an address to a variable. A reference is the address variable, so it can't refer to nothing and can't be reassigned.
When you write
A(const B& b)
you are making a contract. you are stating: "I want to construct A with a mandatory B object. B being null is not an option here."
Delegating to this constructor means following its contract. So with this assumption your delegation works fine with:
struct B{};
struct A{
A() : A(B{}){} // Constructing a pre-defined B object
A(const B& b) : _b{b}{}
B _b;
};
int main ()
{
A a;
}
said that, if you want to express a nullable type you can use std::optional
if C++17 is an option. If you have polymorphic object I'd suggest to use smart pointer to express ownership better and have more control of your code.
Upvotes: 2
Reputation: 36399
Assuming your members of 'A' are references, one way to allow this would be to have some special "null" value for each of your classes:
class B {};
class C {};
class A
{
public:
A();
A(const B& b);
A(const B& b, const C& c);
private:
const B& b_;
const C& c_;
static const B null_b;
static const C null_c;
};
A::A() : A(null_b, null_c) {}
A::A(const B& b) : A(b, null_c) {}
A::A(const B& b, const C& c) : b_(b), c_(c) {
}
Upvotes: 1