re-initialise using delegating constructor - c++

I have this class X, using delegating constructor I want to change only the value i and j as 0. Is it possible to do so?
class X{
public:
X() = default;
X(int ival, int jval) : i{ ival }, j{ jval } {}
X(int new_i) : i{ new_i }, X(i, 0) {} //error here
private:
int i;
int j;
};
int main()
{
X x{ 345, 54 };
x = X{ 34 }; //annoymous copy changes only the i:member
return 0;
}
EDIT: I know X(int new_int) : X{new_int, 0} will work but i wanted to know what's the error if initialise one more variable in the list.
May be I have another z and I want to initialise that along with i and j.
i.e. X(int new_i) :z{ new_i }, X(new_i, 0) {}

Just use
X(int new_i) : X(new_i, 0) {}
From the C++ Draft Standard N3337 (emphasis mine):
12.6.2 Initializing bases and members
6 A mem-initializer-list can delegate to another constructor of the constructor’s class using any class-or-decltype that denotes the constructor’s class itself. If a mem-initializer-id designates the constructor’s class,
it shall be the only mem-initializer;

Why don't you do this?
X(int new_i) :X(new_i, 0){...}
In this way, you will set j-th value to 0, and have only x variable.

You cannot have a delegating constructor and another member-initialiser in the initialiser list. That's not allowed, because the order of initialisation cannot possibly be the order of member declaration, instead some variables will be initialised twice, which is potentially ill-defined.
If your example were allowed, then the constructor in question would first initialise i<-new_i, then i<--i, then j<--0. With non-const int, this may be feasable, but not with more general types.
Simply initialise the objects via the delegation:
class X
{
public:
X() = default;
X(int ival, int jval) : i{ival}, j{jval} {}
X(int ival) : X(ival, 0) {}
private:
int i;
int j;
};
Though in this case, it's better to use default arguments:
class X
{
public:
X() = default;
X(int ival, int jval=0) : i{ival}, j{jval} {}
private:
int i;
int j;
};
You should also consider to use the explicit keyword for single-argument constructors to avoid unpleasant surprises ... as in
void foo(X);
foo(1); // calls foo(X(1));

Related

Why no other constructor is being allowed?

I am learning about initializer list and learnt that const members must be initialized using it, because you cannot initialize it using default constructor or parameterised constructor.
class Foo
{
private:
const int y;
public:
Foo(int yy) :y(yy){}
int getY();
};
Now suppose if I have another member int x; not a const,Why can't I initialize it using default constructor, What is the idea behind this restriction?
The code that gives error:
class Foo
{
private:
const int y;
int x;
public:
Foo(int yy) :y(yy){}
Foo()
{
x = 100;
}
int getY();
};
I am learning about initializer list and learnt that const members must be initialized using it, because you cannot initialize it using default constructor or parameterised constructor.
Const members can be initialized in the member initializer list of both a default constructor and any parametrised constructor. (A default constructor is a constructor that can be invoked without parameters.)
Now suppose if I have another member int x; not a const,Why can't I initialize it using default constructor, What is the idea behind this restriction?
You can initialize any number of members (there is probably some implementation defined limit, but it's not relevant to this question) in the default constructor. There is no such restriction that you describe.
Demo, class with two members, both initialized in the default constructor:
struct Foo {
const int y;
int x;
Foo(): y(1), x(100){}
};
Edit for the mcve.
The code that gives error:
class Foo
{
private:
const int y;
int x;
public:
Foo(int yy) :y(yy){}
Foo()
{
x = 100;
}
int getY();
};
All constructors must initialize const members. Your parametrised constructor does initialize y, but the default constructor doesn't. That is why it doesn't work. See my demo above for a working example.
PS. Your parametrised constructor doesn't initialize x, but that is OK: x isn't const, so you can assign a value to it later.
In my code if I have a parameterised constructor like Foo(int xx) { x = xx;}
It will not give any error
This program:
struct Foo {
const int y;
int x;
Foo(int xx) { x = xx;}
};
Is ill formed in standard C++. If your compiler accepts it without a warning, then it isn't standard compliant.
Unclear what you're trying to accomplish.
Following code simply compiles
class Foo
{
private:
int _nonConst;
const int _const;
public:
Foo() : _const(10), _nonConst(11)
{
}
Foo(int x) : _const(x), _nonConst(x)
{
}
};
I am not sure I understood the question properly. To summarize what you can and can't do:
// .h
class MyClass
{
private:
int x;
const int y;
public:
MyClass();
MyClass(int initValue);
};
// .cpp
// The following is legal
MyClass::MyClass()
: x(0), y(0)
{}
// Alternatively, the following is legal too.
MyClass::MyClass()
: y(0)
{
x = 0;
}
// This is not legal: y cannot be initialized that way as it is const.
// No problem for x though.
MyClass::MyClass()
{
x = 0;
y = 0; // You cannot do that
}
// The following is legal
MyClass::MyClass(int initValue)
: x(initValue), y(initValue)
{}
// Alternatively, the following is legal too.
MyClass::MyClass(int initValue)
: y(initValue)
{
x = initValue;
}
// This is not legal: y cannot be initialized that way as it is const.
// No problem for x though.
MyClass::MyClass(int initValue)
{
x = initValue;
y = initValue; // You cannot do that
}
Of course, you can only have one CTor per declared signature. The examples above are 3 alternatives - 2 legal and 1 illegal - per declared signature.

C++ initialized unnamed struct member in constructor

example:
class A
{
public:
A();
private:
struct {int x, y; } position_;
};
my question is: how to init position_.x and position_.y before the constructor function body? like:
A::A() //init position_.x and position_.y here
{
}
Just use a normal constructor initializer list:
A::A()
: position_{0, 0}
{
}
You can initialize it like any data member1: in the constructor initialization list:
A() : position_{1,2} {}
at the point of declaration:
struct {int x, y;} position_{1, 2};
or both.
1 Assuming you have C++11 or higher

C++ Virtual Inheritance from a non-member function

Coming from a Java/C# background and need a bit of help understanding what is happening here in C++...
class A {
int x;
public:
A(int x) : x(x){}
void f(int y) {
cout << x + y << endl;
}
};
class B : virtual A {
int x;
public:
B(int x) : A(2*x), x(x) {}
virtual void f(int y){
cout << x + 2*y << endl;
}
};
void h(){
B b(5);
A &a = dynamic_cast<A &>(b);
a.f(10);
b.f
}
void g() {
A *a = this;
a->f(10);
B *b = dynamic_cast<B *>(a);
b->f(10);
}
Calling h() is ok but calling g() will not work. Can someone explain why? Also, in the line A(int x) : x(x){} what does : x(x){} do? Same question for B(int x) : A(2*x), x(x) and : A(2*x), x(x).
Thanks so much in advance for your help.
A(int x) : x(x){} what does : x(x){} do?
: x(x) is the initializer list. The variable in the paranthesis is the argument received while the outer one is the member variable. It means member variable x is initialized with the value of the x argument received.
B(int x) : A(2*x)
Here you are calling the base class constructor( i.e, A) that receives an integer. x is the variable received by constructor B. This is a way of calling parameterized base class constructor from derived class constructor. By default, derived class constructor invokes the default base class constructor. In your case, if you don't provide the A(2*x) it fails because the base class has no default constructor.
g() is just a free function and not a member of a class, so this has no meaning. I'm not exactly sure what you're trying to do there
With regards to:
A(int x): x(x)
Your A class has int x as a member. This is calling the constructor of that integer with the x value that is passed into the constructor of A. In my opinion this is bad style and you should differentiate between the two. For example
class A {
int x;
public:
A(int x_in) : x(x_in){}
//...
};
This is equivalent to
class A {
int x;
public:
A(int x_in) {
x = x_in;
}
//...
};
1) As per MSDN (responding to your question related to g());
The this pointer is a pointer accessible only within the nonstatic member functions of a class, struct, or union type. It points to the object for which the member function is called. Static member functions do not have a this pointer.
2) The A(int y) : x(y) {} initializes A::x (the member before () with the value inside the "()" i.e. y (modified variable names for better understanding). Same is the case as with B(int x) : A(2*x), x(x) {}. It calls the base class's (A) constructor with the parameter 2*x and then initializes B::x with the value inside the (), i.e. x.
3) Also, g() wouldn't work because the dynamic_cast<> would throw a compile error since the object that's being casted needs to have at least 1 virtual function. If the only virtual function would be the destructor, then dynamic_cast<> would work.
g is a function at file-scope, aka it doesn't belong to any class. Because of this, you can't use this.
The : x(x)-style expressions are member constructors - they initialize (i.e. call the constructor on) the members of the class.

Using a different base constructor for a derived class C++

From my understanding the following code will execute in this order:
Derived constructor is called.
Base object is constructed using the default base constructor.
Body of the derived constructor executes.
If so, isn't the member z is assigned a value twice?
class base {
public:
int x, y, z;
base() {x = 0; y = 0; z = 0;};
};
class derived : public base {
public:
derived() {z = 5;};
};
Is there a more efficient way to create an object of class "derived" so it uses a different constructor, in this case, one that would only assign members x and y a value, leaving z to be assigned a value in derived()?
Yes, there is a more efficient way, but it will take more code (thus increasing the maintenance overhead).
class base {
public:
int x, y, z;
// Default constructor
base() {x = 0; y = 0; z = 0;};
// Constructor to be called if you want to override the z value
base(int zValue) { x=0; y=0; z=zValue; };
};
class derived : public base {
public:
derived() : base(5) {};
};
Yes, z is assigned twice in your example, just what it looks like.
To do what you're wanting, you could do something like this, which requires almost exactly the same amount of code (just moving some here and there):
class base {
public:
int x, y, z;
base(int z = 0) : x(), y(), z(z) { }
};
class derived : public base {
public:
derived() : base(5) { } // with this one, z is assigned 5 once
// or
derived() { } // z is assigned 0 once
};
Sure. Use what's called a ctor-initializer:
class base {
public:
int x, y, z;
base(int z = 0) : x(0), y(0), z(z) {};
};
class derived : public base {
public:
derived() : base(5) {}
};
The code after the : and before the first { in the constructor declaration is a ctor-initializer. (Some people call it an "initializer list", but ctor-initializer is what the C++ standard calls it.)
You should always use ctor-initializers whenever you can to initialize class members to some value. While it doesn't really matter for ints, initialization using ctor-initializers can be faster than default constructing class members then assignment.
Definitely, you can do that.
Use member-initialization-list as:
class base {
public:
int x, y, z;
base(int a, int b, int c) : x(a), y(b), z(c) {}
//^^^^^^^^^^^^^^^^^^^ it's member-initialization-list!
};
class derived : public base {
public:
derived() : base(0,0,5) {}
// ^^^^^^^^^^^ call the specific base constructor
};
To elaborate on Andrew's answer, if you wanted to really make sure that all of base's members were set only once, and in the most efficient way possible, you could use a member-list initializer rather than setting values in the constructor.
class base {
public:
int x, y, z;
base() : x(0), y(0), z(0) {};
base( int xval, int yval, int zval ) :
x(xval), y(yval), z(zval)
{ };
};
class derived : public base {
public:
derived() : base( 0, 0, 5 ) {};
};
Most compilers will generate the same code for : x(_x), ... as just setting the values in the constructor, but I've seen a couple that did not.

Inheriting constructors in C++0x

Lets say I have the following code in what we expect to become the next C++ standard:
int f(int x)
{
std::cout << x;
return x * x;
}
struct A
{
A(int x) : m_x(x) {}
int m_x;
};
struct B : A
{
using A::A;
B() : m_y(f(m_x)) {}
int m_y;
};
int main()
{
B(5);
}
Would this call the default constructor of B and print out 5 and set m_y = 25? Or will the default constructor of B not run, and leave m_y uninitialized?
And if the latter, what is the rationale behind not calling the B default constructor? It is quite clear that the A(int) B inherits only initialises A, and leaves B in an indeterminate state. Why would C++ choose undefined behaviour over simply calling the default constructor of B()? It largely defeats the purpose of the inheriting constructors feature.
Edit:
Perhaps this should be allowed:
using A::A : m_y(...) { std::cout << "constructing..." << std::endl; ...; }
using A::A; implicitly declares B(int) in the derived class. That is it.
The rest of your program should not work as you expect. Because you're invoking B(int) with B(5), and that leaves m_y uninitialized.
See this example from Bjarne Stroustrup's site:
struct B1 {
B1(int) { }
};
struct D1 : B1 {
using B1::B1; // implicitly declares D1(int)
int x;
};
void test()
{
D1 d(6); // Oops: d.x is not initialized
D1 e; // error: D1 has no default constructor
}
http://www2.research.att.com/~bs/C++0xFAQ.html#inheriting
Another example from the same link:
struct D1 : B1 {
using B1::B1; // implicitly declares D1(int)
int x{0}; // note: x is initialized
};
void test()
{
D1 d(6); // d.x is zero
}