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});
Related
Trying to figure out how to efficiently and safely reference global custom type constants that are initialized at compile time. I want to avoid copying of Foo as I will be creating a lot of Bar instances and Foo is a bit more complicated than shown here. Keeping a const reference from Bar to Foo appears to be safe (or is it?) but at the same time I don't know how to prevent the "badBar" usage if possible. Any suggestions?
class Foo
{
int a_, b_;
public:
constexpr Foo(int a, int b) : a_(a), b_(b) {}
};
inline constexpr Foo kFoo{1, 2};
class Bar
{
const Foo& foo_;
public:
Bar(const Foo& foo) : foo_(foo) {}
const Foo& foo() { return foo_; }
};
int main() {
Bar goodBar(kFoo);
Bar badBar(Foo(3, 4)); // ouch
return 0;
}
Yes, keeping a reference to globally defined constant variable is safe as it will always be valid.
You can just initialize the member directly:
class Foo
{
int a_, b_;
public:
constexpr Foo(int a, int b) : a_(a), b_(b) {}
};
inline constexpr Foo kFoo{1, 2};
class Bar
{
const Foo& foo_=kFoo;
};
The rest of the world does not have to know it exists and makes the ctor of Bar simpler.
Although it feels slightly redundant, anywhere you can write foo_, you can also write kFoo. Maybe I am misunderstanding your question?
You can add an rvalue constructor to discard rvalue arguments.
class Bar
{
const Foo& foo_;
public:
Bar(const Foo& foo) : foo_(foo) {}
Bar(Foo &&) = delete; // <-- rvalue constructor
const Foo& foo() { return foo_; }
};
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()) {}
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()) {...}
};
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 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.