This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
Closed 4 years ago.
class Sales_data {
public:
Sales_data(int i, int j, int k) : x(i), y(j), z(k) {
}
private:
int x,y,z;
};
In the above code(more specifically in Sales_data constructor(recited below)), I don't understand the use of colon and comma separated list.
Sales_data(int i, int j, int k) : x(i), y(j), z(k) {
}
I have never seen a colon(":") following any function/constructor parameter list. What does this colon mean/signify here ?
Moreover, what is this comma separated list after colon ?
You may be confused, because the member variable name (x) is same as the function parameter (also x), which you can always avoid for clarity. Simplified code can look like so.
add_x(int x1) : x(x1) // a contructor that initializes the member vaiable x to x1
{
}
Still confused? then you can go for this ( not so optimize though)
add_x(int x1)
{
x = x1;
}
This is a constructor
This is not a standard function/method. Each class (struct) can have constructor(s). The constructor has the same name as the class and can optionally take parameters.
struct add_x {
int x;
add_x(int x) : x(x) {} // This is a constructor with one paramter
};
To make it easier to read let us format it better.
struct add_x {
int x;
add_x(int x) // Constructor that takes one argument.
: x(x) // This is called the initializer list.
{} // This is the body of the constructor.
};
The initializer list allows you to list out the member variables (comma separated) and initialize them before the body of the constructor is executed.
In this case the member x is initialized with the parameter x.
#include <iostream>
int main()
{
add_x test(5);
std::cout << test.x << "\n"; // Should print 5
// Note in my example I have removed the private
// section so I can read the value x.
}
Related
This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
Closed 3 years ago.
i don't know the meaning of
Name_value(std::string n, int v)
:name(n), value(v) { }
how do these two lines work?
#include "std_library_facilities.h"
void error(std::string b)
{
throw std::runtime_error(b);
}
class Name_value
{
public:
std::string name;
int value;
Name_value(std::string n, int v)
:name(n), value(v) { }
};
int main()
{
}
There are no vectors involved here; what you see is the declaration of a class Name_value and its constructor Name_value::Name_value(std::string, int).
Constructors are a really basic thing that you're going to have to understand before you do anything in C++.
A constructor is a special class member that sets up a new object of that class type. In this case, the constructor 's definition (declared inline in the class definition)
Name_value(std::string n, int v):
name(n), value(v) { }
sets any new Name_value object's name member to the value of n and it's value member to v
So, if your main contains something like this
int main()
{
Name_value n ("foo", 8);
}
Then n.name would be set to a std::string containing "foo" and n.value would be set to 8.
Name_value(std::string n, int v) is a constructor for Name_value taking two arguments (n and v).
: name(n), value(v) is the constructors initialization list where you initialize class member variables. In this case, the member name is initialized from n and value is initialized from v.
The { } bit is the body of the constructor - which is empty because nothing except initialization (which has already been done) needs to be done for this constructor.
This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
Closed 5 years ago.
I saw this piece of code
class Foo {
public:
int x;
double y;
float z;
Foo(int x, double y, float z)
// XXX: What are the following doing?
: x(x),
y(y),
z(z) {}
}
I'm guessing what was written after the : is assigning the values to the members (x, y, z ) from the arguments.
Question 1: Why that way and not the following?
Foo(int x, double y, float z) {
this->x = x;
this->y = y;
this->z = z;
}
Question 2: in the original style, how does the compiler distinguish the member x from the parameter x? (In my modified pice of code, the qualifier this was used for that purpose)
For example, if I were to write this:
Foo(int x, double y, float z)
// XXX: What are the following doing?
: x(x * 2),
y(x * 3 + y ), // which 'x' is the 'x' in 'x * 2'?
z(z) {}
}
You guess correctly. Those are member initializer lists. The reason this is preferred over directly assigning in the constructor is because it is necessary for const class members, classes with no default constructors, and reference variables. Example:
class A
{
int b;
public:
A(int c) : b(c) {}; // No default constructor
};
class Test
{
A a; // A class with no default constructor
const int x; // A constant
int& r; // A reference
public:
Test(int d) : a(5), x(2), r(d) {};
};
int main()
{
Test test;
}
In this example, both members a and x of class Test cannot be assigned to because the first has no default constructor, while the latter is constant, meaning assignment to it would create an error. Finally, since reference variables cannot be assigned to, an initializer list is needed.
In the end, the primary difference comes down to the fact that initializer lists initialize the variable (who knew?), while assignment in the constructor is done after those member variables' constructors have been called.
As for your second question, you can see for yourself that the parameters are picked before the member variables during the initialization.
That is not a duplicate. Please read carefully. There are two variables x (of type int and X) and one member is actually declared private, which is used in a constructor. It is about understanding the constructor process in this very specific case.
I am doing a C++ course and I understand the following example that was given. It is about constructors.
#include <iostream>
using namespace std;
class Element {
int value;
public:
Element(int val) {
value = val;
cout << "Element(" << val << ") constructed!" << endl;
}
int Get(void) {
return value;
}
void Put(int val) {
value = val;
}
};
class Collection {
Element el1, el2;
public:
Collection(void) : el2(2), el1(1) {
cout << "Collection constructed!" << endl;
}
int Get(int elno) {
return elno == 1 ? el1.Get() : el2.Get();
}
int Put(int elno, int val) {
if (elno == 1) el1.Put(val);
else el2.Put(val);
}
};
int main(void) {
Collection coll;
return 0;
}
Then they mentioned the following
...
We should also add that there is the following alternation for that
case: when the constructor is divided between the declaration and the
definition, the list of alternative constructors should be associated
with the definition, not the declaration.
It means that the following snippet is correct:
class X {
public:
X(int x) { };
};
class Y {
X x;
public:
Y(int x);
};
Y::Y(int x) : x(1) { };
Can someone explain? Is it really correct? And if yes, how to interpret that? Y has a one-parameter constructor, but no value is passed. x(1) is probably the constructor for the field X x in Y. Is the value of 1 (of x(1)) then passed to Y(int x) automatically although it is declared private in Y?
In the second code snippet, there is no construction actually going on—it's just a definition of the classes and constructors. The only "special" thing about it is that the body of Y's constructor is defined outside the class; it could be in a different file, for example. In this case, it's no different from putting the body directly into the class1:
class Y {
X x;
public:
Y(int x) : x(1) {}
};
When this constructor of Y is invoked, it constructs the member variable x by passing 1 to the X constructor taking int. The constructor of Y doesn't do anything else, i.e. it ignores its own parameter.
The syntax Y::Y used in the original code snippet is standard syntax for defining a member function outside of the class definition. For a non-constructor, it would look like this:
class Foo
{
int bar() const;
};
int Foo::bar() const
{
return 42;
}
1 With the slight difference that when put directly into the class definition, the function is implicitly inline (can be present in more than one translation unit).
Full code. Line specified later.
#include <iostream>
#include <string>
using namespace std;
class X
{
private:
int i;
float f;
char c;
public:
X(int first=1, float second=2.0, char third='a') : i(first) , f(second) , c(third) { }
void print() { cout << i << " " << f << " " << c << endl;}
};
int main()
{
X var1;
var1.print();
return 0;
}
What exactly is going on on this line:
X(int first=1, float second=2.0, char third='a') : i(first) , f(second) , c(third) { }
As far as I can understand (could be wrong), we are declaring objects first, second, and third of type (class) X. We are initializing them during declaration. What's going on after the colon? What's going on altogether?
What exactly is going on on this line:
X(int first=1, float second=2.0, char third='a')
: i(first) , f(second) , c(third) {
}
It's a constructor which takes 3 parameters with default values.
This part : i(first) , f(second) , c(third) is called a member initializer list.The member initializer list consists
of a comma-separated list of initializers preceded by a colon. It’s placed after the closing
parenthesis of the argument list and before the opening bracket of the function body.
Only constructors can use this initializer-list syntax. const class members must be initialized in member initializers.
The stuff in the parenthesis are default values for the arguments to the constructor, and the stuff after the colon initializes those items after the colon.
The colon notation is most commonly used to invoke the constructors of other objects the class uses.
You have class X with three fields: i, f, c.
You have defined a constructor with three default parameters - when this constructor invoked fields are initialized with parameters (passed to constructor or defaults).
It's like:
X (int first=1, float second=2.0, char third='a')
{
i = first;
f = second;
c = third;
}
Your line is just an another way to initialize fields, usually they are equal (there are some differences with inheritance).
In your main code you're creating a local variable var1 of type X, so the constructor is called. You don't pass any parameters, so default values are used.
As result, you have one local object of type X initialized with default values listed in constructor.
X(int first=1, float second=2.0, char third='a') : i(first) , f(second) , c(third) { }
This is a constructor for X. There are three agruments, each having a default value so that it can be invoked in different ways
X myX;
X myX(first);
X myX(first, second);
X myX(first, second, third);
The section after the arguments
: i(first) , f(second) , c(third)
are initializers for the i, f and c members. If possible this style of initialization is preferred over initialization in the function body, and if the members are constant types, this style is required.
Then there is an empty body for the constructor {}
What is the difference between this two constructor?
int x, y; //position
BasePoint(int px, int py) : x(px), y(py) {}
and
int x, y; //position
BasePoint(int px, int py)
{
x = px;
y = py;
}
What is x(px), y(py) called? And When do I use this type of variable initialization?
Thanks.
First one is doing initialization using initialization-list, and second one is doing assignment using assignment operator.
First one is recommended!
BasePoint(int px, int py) : x(px), y(py) {}
^^^^^^^^^^^^^ this is called initialization-list!
Read this FAQ : Should my constructors use "initialization lists" or "assignment"?
The FAQ answer starts with :
Initialization lists. In fact,
constructors should initialize as a
rule all member objects in the
initialization list. One exception is
discussed further down [...]
Read the complete answer.
What is x(px), y(py) called?
These are called initializer lists. What you are actually doing is copying the value of px to x and py to y.
Uses:
class foo
{
private:
int numOne ;
public:
foo(int x):numOne(x){}
};
class bar : public foo
{
private:
int numTwo;
public:
bar(int numTwo): foo( numTwo ), // 1
numTwo(numTwo) // 2
{}
};
bar obj(10);
1. Notice that derived constructor's argument can be passed to base class constructor.
2. Compiler can resolve, in this case, which one is argument and which one is member variable. Had if, this needs to be done in the constructor,then -
bar::bar(int numTwo) : foo( numTwo)
{
this->numTwo = numTwo; // `this` needs to be used. And the operation is called assignment. There is difference between initialization and assignment.
}
BasePoint(int px, int py) : x(px), y(py) {}
here u are using the initialization list
so the object when constructed will not go inside the body and initiate those values.it saves time by not entering in the body of the constructor
Another use of this is when calling the derived class constructor.
where if you use the statement like
new derivedclass(a,b,c)
and you can write this
derivedclass(int x,int y,int z):baseclass(a,b),h(z){}