I have a constructor for B with some default argument depending on other arguments:
struct A
{
int f();
A(const A&) = delete;
A(A&& );
// ....
};
struct B
{
B(A a, int n=a.f()) {//...}
// ...
};
This clearly does not work in that way, so I want use a delegate constructor:
struct B
{
B(A a, int n) {//...}
B(A a): B(a, a.f()) {}
};
This, however, also does not work because the copy constructor of A is deleted. So I need something like
struct B
{
B(A a, int n) {//...}
B(A a): B(std::move(a), a.f()) {}
};
As far as I know, however, there is no guarantee that a.f() is evaluated before std::move, so the result is undefined. Is there a possiblity to get the value of a.f() before std::move or should I better write two seperate constructors?
Why don't you do something simpler - i.e. overload your constructor?
struct B
{
B(A a) {
int n = a.f();
...
}
B(A a, int n) {
...
}
};
If you don't like repetition of your code in ..., you can always have just a single call to a private member function that does the rest of the construction.
The are more possible solutions for this.
The most simple approach is to make a a pointer:
struct B
{
B(A* a, int n) {...}
B(A* a): B(a, a->f()) {}
};
A more complex approach is to try to make a a reference:
struct B
{
B(A& a, int n) {...}
B(A& a): B(a, a.f()) {}
};
I would not suggest this solution. The pointer is a cleaner approach.
Edit:
Via std::move from the utility libary
struct B
{
A&& a:
int n:
B(A&& a, int n): a(std::move(a)), n(n) {...}
B(A&& a): B(std::move(a), a.f()) {...}
};
Related
In the following situation:
class A
{
protected:
int m_int;
A() : m_int{-2} {};
public:
A(const A& a) { m_int = a.get(); }
A& operator=(const A& a) { m_int = a.get(); return *this; }
int get() const { return m_int; }
};
class B : public A
{
protected:
using A::m_int;
public:
// same constructors as parent, but public
using A::A;
};
class C : public B
{
public:
// same constructors as parent
using B::B;
C(int x) { m_int = x; }
C(const B& b) { C(b.get()); }
};
class D : public C
{
public:
// same constructors as parent
using C::C;
D(const B& b) { D(b.get()); }
};
int main()
{
C c(5);
D d(c);
return d.get();
}
I would expect for main() to return 5. Instead, it returns -2. It seems it's calling the default constructor of A, whereas I would have expected for it to call the D(const B& b) constructor. What's going on?
Why do I need to provide an explicit constructor for C(const B& b)? I would have guessed for a default behavior to be deduced, for inheritance reasons. What am I missing?
The problem is the constructor in D:
D(const B& b) { D(b.get()); }
This will be the constructor that is called. And it doesn't copy the value from b, instead it creates a new and temporary D object which is promptly destructed as the constructor function exit.
You have the same problem in the corresponding C constructor:
C(const B& b) { C(b.get()); }
You should use a constructor initializer list to delegate to the correct constructor:
D(const B& b) : C(b.get()) {}
According to my research, C++ does not automatically inherit constructors in subclasses, so given the code below:
struct foo
{
int a;
int b;
foo(int a, int b) : a(a), b(b) {}
foo() : a(0), b(0) {}
};
struct bar : foo{};
struct baz
{
int a;
baz(int a) : a(a) {}
baz() : a(0) {}
};
struct qux : baz{};
We should not be able to create an object baz in the same way as foo without first redefining the constructor.
int main(){
bar b(1,2);
std::cout << b.a;
}
gives an error as we should expect. However
int main(){
qux b(1);
std::cout << b.a;
}
returns 1, despite qux having no explicit constructor. Did it receive its constructor from baz or is this a quirk of it being a single parameter constructor, or is it something else?
Also, if I do go in and add the constructor to bar
bar(int a, int b)
{
this->a = a;
this->b = b;
}
and
bar(int a, int b) : foo(a,b) {} work, but bar(int a, int b) : a(a), b(a) {} does not. Why is this?
Thanks a bunch.
qux b(1);
works because implicit conversion takes place (from int to baz)
and then move constructor is used to create qux from baz
delete move constructor or make baz(int) constructor explicit and it will not work
struct baz
{
int a;
baz(const baz& o) = delete;
/*explicit*/ baz(int a) : a(a) {}
baz() : a(0) {}
};
as for
but bar(int a, int b) : a(a), b(a) {} does not.
it will work if you create foo and pass it to move constructor like this:
bar b({1,2});
Perhaps my title might translate to "apples vs oranges", but I'm not quite sure so I'd like the SO community's help understanding some best practices.
Suppose I have the two examples.
brace-or-equal initialization
class foo
{
public:
foo() {}
foo(int a) : m_a(a) {}
foo(int a, int b) : m_a(a), m_b(b) {}
foo(int a, int b, int c) : m_a(a), m_b(b), m_c(c) {}
private:
int m_a = 1;
int m_b = 2;
int m_c = 3;
};
constructor delegation
class foo
{
public:
foo() : m_a(1), m_b(2), m_c(3) {}
foo(int a) : foo() { m_a = a; }
foo(int a, int b) : foo() { m_a = a; m_b = b; }
foo(int a, int b, int c) : foo() { m_a = a; m_b = b; m_c = c; }
private:
int m_a;
int m_b;
int m_c;
};
I feel like the first is better because it results in no double-initialization of variables. In the 2nd example, the last overload of foo's constructor is the worst because each member variable is initialized twice.
Which is the preferred method here? And assuming the former is preferred, when are delegated constructors useful?
You want to delegate from the constructor that takes fewer arguments to the constructor that takes the most, giving default values for the extra parameters:
foo( int a, int b, int c ) : m_a(a), m_b(b), m_c(c) {}
foo( int a, int b ) : foo( a, b, 3 ) {}
foo( int a ) : foo( a, 2, 3 ) {}
foo() : foo( 1, 2, 3 ) {}
Like clcto pointed out, you should do delegation differently.
In reality we can do a little better (With your given example!!!) using default param values:
class foo
{
public:
// no longer need all your other constructors
foo(int a=1, int b=2, int c=3) : m_a(a),m_b(b),m_c(c){}
private:
int m_a;
int m_b;
int m_c;
};
Your actual code may be different; i.e. you want to sometimes initialize b and not a or c, so you could instead use one of the other answers posted.
I have the following classes:
class A
{
public:
A() { x = 0; std::cout<<"A default ctor()\n"; }
A(int x_) { x = x_; std::cout<<"A normal ctor()\n"; }
int x;
};
class B
{
public:
B() { std::cout<<"B ctor()\n"; }
private:
std::string str;
};
and a function which creates an object B, taking an object A as parameter:
B
createB(const A& a) {
std::cout<<"a int: "<<a.x<<"\n";
return B();
}
if I design a class C, which has members of type A and B and constructs the B-object before A-object is constructed but using the A object to do so, this will compile without warnings but it will silently enter a bug:
class C
{
public:
C(): b(createB(a)), a(10) {}
private:
B b;
A a;
};
int main()
{
C c;
return 0;
}
Of course, the above example is a trivial one, but I've seen it in real world, in much more complex code (it's Friday, 8:30 PM and I just fixed this bug which led to segfaults).
How can I prevent this from happening?
I would agree with what others have suggested, namely that the onus is on the designer to ensure that objects are initialized before use. I see two ways of doing that in your case:
First (and easiest), reverse the order of a and b in the class definition:
class C
{
public:
C(): b(createB(a)), a(10) {}
private:
A a;
B b;
};
Second, you could move a to a base class if you want to really emphasize that it's initialization occurs before that of other members:
class CBase
{
protected:
CBase(): a(10) {}
protected:
A a;
};
class C : private CBase
{
public:
C(): b(createB(a)) {}
private:
B b;
};
I see three possible alternatives:
Require A to be constructed prior to constructing C:
class C
{
public:
C(const A& a) : a_(a), b_(a) {}
private:
A a_;
B b_;
};
Construct A prior to constructing 'B':
Delaying the construction of B until A is complete. This stops the undefined behavior from happening, but doesn't enforce proper behavior via the interface (as options 1 and 3 do)
class C
{
public:
C() : a_(/* construct as appropriate */)
{
b_.reset(new B(a_));
}
private:
A a_;
std::unique_ptr<B> b_;
};
If the design allows for it, have B contain (and expose) A.
This appears possible from the trivial example, but in real life may not be:
class B
{
public:
const A& my_a() {return a_;}
private:
// construct as appropriate (?)
A a_;
};
class C
{
private:
B b_;
};
I have a class with const members, and one constructor which calls another constructor with extra values filled in. Normally I could use a colon initializer for this, but the function is complex (printf/sprintf-like) and requires me to use a variable on the stack, so I have to do this in the body of the constructor and use assign *this to the new object. But of course this is invalid, because my member variables are const.
class A
{
public:
A(int b) : b(b), c(0), d(0) // required because const
{
int newC = 0;
int newD = 0;
myfunc(b, &newC, &newD);
*this = A(b, newC, newD); // invalid because members are const
// "cannot define the implicit default assignment operator for 'A', because non-static const member 'b' can't use default assignment operator"
// or, sometimes,
// "error: overload resolution selected implicitly-deleted copy assignment operator"
};
A(int b, int c, int d) : b(b), c(c), d(d) { };
const int b;
const int c;
const int d;
};
A a(0);
(I haven't explicitly deleted the assignment operator.) I declared the members const because I would like them to be public, but not mutable.
Is there some canonical way of solving this problem without using scary casts and force-overriding the members' constness? What's the best solution here?
You can add a parameters class and use either C++11 constructor delegation or a base class:
struct parameters {
int b; int c; int d;
parameters(int b): b(b), c(), d() {
myfunc(b, &c, &d);
}
};
// constructor delegation
class A {
public:
A(int b): A(parameters(b)) { }
A(parameters p): b(p.b), c(p.c), d(p.d) { }
};
// base/wrapper
class ABase {
ABase(parameters p): b(p.b), c(p.c), d(p.d) { }
};
class A: public ABase {
public:
A(int b): ABase(parameters(b)) { }
};
How about making a helper function:
class A
{
static int initializor(int b) { int n; myfunc(b, &n); return n; }
public:
explicit A(int b_) : b(b_), c(initializor(b_)) { }
A(int b_, int c_) : b(b_), c(c_) { }
// ... as before ...
};
I prefer Kerrek SB's answer, but in your case there is the complication that you can't easily make separate initialisation functions for each member.
In that case, another solution is to move the members to a base class and initialize that base class with a helper class with non-const members. Your initialization code is moved to the helper class' constructors, and can assign without problems.
class A_init
{
public:
A_init(int b)
{
// do whatever you like with c and d:
c = ...;
d = ...;
}
int c; // Note: non-const
int d; // Note: non-const
};
class A_base
{
public:
A_base(int b, A_init init) : b(b), c(init.c), d(init.d) {}
A_base(int b, int c, int d) : b(b), c(c), d(d) {}
const int b;
const int c;
const int d;
};
class A : public A_base
{
public:
A(int b) : A_base(b, A_init(b)) {}
A(int b, int c, int d) : A_base(b, c, d) {}
};
If one wants restrict access to A_init, one can switch to private and declare A a friend.
Where to put the results of myfunc so it can be set and used from different mem-initializers? How about in a default argument?
class A
{
private:
struct InitData;
public:
A(int b, InitData data=InitData());
A(int b, int c, int d) : b(b), c(c), d(d) { };
const int b;
const int c;
const int d;
};
struct A::InitData
{
int setup(int b);
int c;
int d;
};
inline int A::InitData::setup(int b)
{
myfunc(b, &c, &d);
return b;
}
inline A::A(int b_, InitData data)
: b(data.setup(b_)),
c(data.c),
d(data.d) {}
A a(0);
Since the made up type is private and has no conversions, there's little risk of accidentally using it or abusing it.