Class member initializer:syntax and usage - c++

Say there is a class:
class person {
int age;
string name;
public:
person(int age,string name)
:age(age),name(name)
{}
};
I have the following questions:
Can the constructor initializer(with the ":" syntax) be used somehow outside of classes?Is it just for classes?
A variable declaration such as int x(2) works for obvious reasons.x is an object with value of 2.But age(age),how does that work?Is the syntax made that way to make initialization easier?
Based on that,how come can the parameter age & member age have the same name and not confuse the compiler?Member age is in scope(as a private member),but parameter age is also in scope.When this happens with ordinary functions,the "localest" is the one that prevails.
Thanks!

It doesn't 'confuse' the compiler. Since it's a member initializer list it's scope is the same as constructor. Therefore function scope wins over class scope. And therefore the member age is initialized with the paramter age.
Normally I would not use the same name (even though certainly possible) as it's both brittle and somewhat unclear. For example:
struct Decision {
bool launch_nukes;
Decision(bool /*launch_nukes*/) : launch_nukes(launch_nukes) {
}
};
At best will only give a warning.

Can the constructor initializer(with the ":" syntax) be used somehow outside of classes?Is it just for classes?
Member initializer lists can only be used by constructors only.
A variable declaration such as int x(2) works for obvious reasons.x is an object with value of 2. But age(age), how does that work? Is the syntax made that way to make initialization easier?
Based on that,how come can the parameter age & member age have the same name and not confuse the compiler? Member age is in scope, but parameter age is also in scope. When this happens with ordinary functions, the "localest" is the one that prevails.
we have and expect member(init), so for member, only members of the class are seen (and Base class or own class for delegating constructor). We can say that we are only in the scope of the class.
For init, indeed regular scope applies, and parameters age/name hides members with same name.

Related

Clarification on C++ constructor syntax

I am curious as to whether any clarification can be provided on the multitudes of constructor syntax's there are in C++. I have seen constructors declared inside of classes, and outside of classes. I have also seen variable initialization through more common methods such as x = y or this-> x = y, but also through initialization lists, like Point(int i = 0):x(i) {}.
My question is whether there are certain situations where it is more suitable to use one style of constructor over another, or whether to declare the constructor inside or outside the class. Is their some commonly followed syntax guideline for this?
I feel it is generally a good idea to have constructors' destructors and other methods' prototypes inside the class itself, if they belong to the same class. It is more efficient and more programmer friendly.
for eg:
I would do something like this:
class decl ....{
private:
members var.. methods' prototype..
public:
decl(); default cons prototype
decl(type para....); parameterized cons prototype;
~decl();
some methods' prototypes..
};
Then you can always go ahead and use them take an argument to assign the value to instant variable
such as this:
decl::decl(can user the same name or different ){
if using the same name
this -> sameName = sameName;
otherwise,
instant data variable name = assign the value,
}

How to define a Struct with default values?

Rather surprised to find this question not asked before. Actually, it has been asked before but the questions are VERY DIFFERENT to mine. They are too complicated and absurd while I'll keep it simple and to the point. That is why this question warrants to be posted.
Now, when I do this,
struct A {
int a = -1;
};
I get the following error:
ANSI C++ forbids in-class initialization of non-const static member a
Now, along with the workaround can someone please tell me THE BEST way of initializing a struct member variable with a default value?
First, let's look at the error:
ANSI C++ forbids in-class initialization of non-const static member a
Initialization of a true instance member, which resides within the memory of an instance of your struct is the responsibility of this struct's constructor.
A static member, though defined inside the definition of a particular class/struct type, does not actually reside as a member of any instances of this particular type. Hence, it's not subject to explaining which value to assign it in a constructor body. It makes sense, we don't need any instances of this type for the static member to be well-initialized.
Normally, people write member initialization in the constructor like this:
struct SomeType
{
int i;
SomeType()
{
i = 1;
}
}
But this is actually not initialization, but assignment. By the time you enter the body of the constructor, what you've done is default-initialize members. In the case of a fundamental type like an int, "default-initialization" basically boils down to "eh, just use whatever value was in those bytes I gave you."
What happens next is that you ask i to now adopt the value 1 via the assignment operator. For a trivial class like this, the difference is imperceptible. But when you have const members (which obviously cannot be tramped over with a new value by the time they are built), and more complex members which cannot be default-initialized (because they don't make available a visible constructor with zero parameters), you'll soon discover you cannot get the code to compile.
The correct way is:
struct SomeType
{
int i;
SomeType() : i(1)
{
}
}
This way you get members to be initialized rather than assigned to. You can initialize more than one by comma-separating them. One word of caution, they're initialized in the order of declaration inside your struct, not how you order them in this expression.
Sometimes you may see members initialized with braces (something like i{1} rather i(c)). The differences can be subtle, most of the time it's the same, and current revisions of the Standard are trying to smooth out some wrinkles. But that is all outside the scope of this question.
Update:
Bear in mind that what you're attempting to write is now valid C++ code, and has been since ratification of C++11. The feature is called "Non-static data member initializers", and I suspect you're using some version of Visual Studio, which still lists support as "Partial" for this particular feature. Think of it as a short-hand form of the member initialization syntax I described before, automatically inserted in any constructor you declare for this particular type.
You could make a default constructor
struct A {
A() : a{-1} {}
int a;
};

difference in declaration of member objects

This is probably a very basic question but I never got around to understanding it properly. When I declare member variables I usually do within a class
class Bloke
{
public:
Bloke(): age(24) {}
int age;
}
So, I usually declare after the semicolon the member variables with "membera(), memberb()" etc. Over time I got a bit lazy and started to also include declarations of the member variables directly in {}, that is
Bloke(){age=24;}
int age;
Or even outside the class in the constructor separately. Can someone please explain if this is wrong? Thanks.
No it is not wrong and up until c++11 it was the only way. Most people however would consider the first way to be easier and more idiomatic for c++11, it is called constructor delegation. In c++11 you can also do inline initialization for some types like this:
class Bloke
{
public:
Bloke():{}
int age = 24;
};
The value for age will be 24 unless you change it somewhere else for all initialized objects. IMO constructor delegation should be used for any situation where applicable and save the body of the constructor for extra work.

Clarification of some details on the Class definition and implementation in C++ for a beginner

I am a beginner in C++ and am trying to learn it by looking at examples.
Here is an example definition for a class that I don't understand the meaning completely:
class MyClass{
public:
std::string name;
void *data;
MyClass(const std::string& t_name, void *t_data) : name(t_name), data(t_data) {}
};
Here is what I understand:
name and *data are variables of the class and, MyClass(...) is the constructor. The meaning of : is the left side class is derived from the right hand side class. However, what is the meaning of this part of the code:
MyClass(const std::string& t_name, void *t_data) : name(t_name), data(t_data) {}
Here are the questions:
what are "t_data" and "t_name"? Are they initial values for "data" and "name"? what is the reason t_ is used here?
what is the meaning of : in the above line?
what is {} at the end of that line?
Thanks for the help.
TJ
what are "t_data" and "t_name"? Are they initial values for "data" and "name"?
They are the arguments passed to the constructor. If an object were created as
MyClass thing("Fred", some_pointer);
then, in the constructor, t_name has the value "Fred" and t_data has the value of some_pointer.
what is the reason t_ is used here?
Some people like to tag the arguments to give them different names to the class members, but there's no need to do that unless you want to.
what is the meaning of : in the above line?
That marks the start of the initialiser list, which initialises the class member variables. The following initialisers, name(t_name), data(t_data) initialise those members with the constructor's arguments.
what is {} at the end of that line?
That's the constructor's body, like a function body. Any code in their will be run after the members have been initialised. In this case, there's nothing else to do, so the body is empty.
It is good C++ practice to use initializer lists to initialize members.
t_name, t_data are the parameter names.
The "t_" prefix is merely used to distinguish it from the similarly named member fields.
The members are being initialized using syntax that resembles a function call, but it is a proper initialization/construction, so you should think of it that way.
The colon signals the beginning of an initializer list
The empty braces {} designate that the body of the constructor (which happens after the members are initialized) is empty.
MyClass(const std::string& t_name, void *t_data) : name(t_name), data(t_data) {}
is constructor of your class, and you should initialize your class with a string and void* parameter, then you initialize your class fields (name and data) with your passed parameters
This is a somewhat compressed example for a beginner, but you're asking good questions.
1) t_data and t_name are the parameters going into the constructor. When you create an instance of this class, you'll do something like:
MyClass * myNewClassInstance = new MyClass("My name", &myData);
Now the constructor has "My name" (in std::string form) as t_name and a pointer to myData as t_data.
2) The colon here does not refer to a derived class. Here it says that an "initializer list" is to follow. Check out Prashant's answer's link, or do a little digging about this. Basically, this is setting the member variable name to t_name (which is the std::string that we passed into the constructor in the above example), and data to t_data (the void pointer). (see additional notes below)
3) The {} is the actual definition of the constructor. It's empty -- there's no code here. So all the constructor will do is initialize the member variables (as defined by the initializer list), and nothing more.
Now let's look at the exact same class in a more beginner-friendly format:
// The declaration of MyClass. This would often show up in a header (.h) file
class MyClass {
public:
// Member variables
std::string name;
void * data;
// Declaration of constructor -- we haven't defined what actually does here, just
// what parameters it takes in.
MyClass(const std::string& t_name, void * t_data);
}
// We declared what the class "looks like" above, but we still have to define what
// the constructor does. This would usually show up in a .cpp file
// This is the constructor definition. We have to specify that it's part of the
// The extra "MyClass::" specifies that it's part of the MyClass namespace that we
// declared above.
MyClass::MyClass(const std::string& t_name, void * t_data)
{
// Set our member variables to what was passed in.
this.name = t_name;
this.data = t_data;
}
The above version does exactly the same thing (with some subtle differences between initializer lists and traditional initialization in the constructor that you probably don't care about yet -- again, see other references regarding this if you're curious).
It's pretty obvious that this takes up a lot more space, and that's exactly why the more compressed format is often used. But when you're just starting out, it makes things a lot more clear doing it this way. It's important to understand the difference between a declaration and a definition when it comes to functions (i.e. the constructor), because the example you posted does both at the same time when often they are separated.
I am a beginner in C++ and am trying to learn it by looking at examples.
For whatever reason, this is harder to do in C++ than it is in Perl, Python, Java, or even C. I don't recommend this course; instead, you might invest in a good book.
Here is what I understand:
Let's start with that. I don't think you understand as much as you claim to.
name and *data are variables of the class
No. name and data are variables of the class. Their types are std::string and void*, respectively.
MyClass(...) is the constructor.
Yes.
The meaning of : is the left side class is derived from the right hand side class.
No, : means different things in different contexts. In the context in which it is used in your sample, it indicates that an initializer list follows.
However, what is the meaning of this part of the code:
what are "t_data" and "t_name"?
They are local variables in the constructor function. Specifically, they are the passed-in parameters to the function.
Are they initial values for "data" and "name"?
That is how they are being used in this sample. Specifically, they are being passed to the data and name initializers in the initializer list.
what is the reason t_ is used here?
This is purely the convention of this particular author. I've never seen that convention before.
what is the meaning of : in the above line?
It introduces an initializer list. This construct is only used in constructor member functions. Each named member is initialized by the values listed. (Note: the values do not need to come from parameters -- they can be any legal expression, so: MyClass(int ii) : i(ii), j(cos(0) / 2), k(&global_variable) {} might be a legitmate constructor. )
what is {} at the end of that line?
The body of the constructor member function. Since all of the work of the constructor is being done in the initializer list, the body of the function is empty.

Classes in C++ with Ctor [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
The Definitive C++ Book Guide and List
i have a lot of questions about declaration and implementation, according to most (books, tutorials, blog entries) a class declaration with constructor, methods and member functions:
class Book
{
public:
Book(const string & author_,
const string & title_,
const string & publisher_,
double price_,
double weight_);
string getName()
{
string name;
name = author + ": " + title;
return name.substr(0, 40);
}
double getPrice();
double getWeight();
private:
string author, title, publisher;
double price, weight;
};
i understand all the the access level, the Constructor, reference operator (pointer too!), the pointer operator, but when I read things less trivial like:
class Type
{
public:
enum TypeT {stringT, intT, doubleT, unknownT};
// 1. which means "explicit"?
// 2. what's ": typeId(typeId_)"? after the Ctor declaration
explicit Type(TypeT typeId_) : typeId(typeId_) {}
// 3. "const" after the declaration which means?
BaseValue * newValue() const
{
return prototypes[typeId]->clone();
}
TypeT getType() const
{
return typeId;
}
static void init();
{
prototypes[stringT] = new Value<string>("");
prototypes[intT] = new Value<int>(0);
prototypes[doubleT] = new Value<double>(0);
}
private:
TypeT typeId;
static vector<BaseValue *> prototypes;
};
I feel lost and really have not found clear information about the above points.
Addition to answering my question, if you know somewhere where they have these "tricks" of language
A good introductory book to C++ should answer your questions.
explicit means the constructor must be mentioned explicitely in the code, the type cannot be constructed automatically from another type when required.
Member initialization. The class member is not constructed with its default constructor, but rather the arguments given here.
The method can be called on a const object.
1) By default, c++ will assume that any constructor taking one argument of another type can be used as an "implicit conversion" from the arg's type to the constructor's type; in your example, this would allow you to pass a TypeT into any function expecting a Type, and the constructor would assume you want it to run the Type(TypeT) constructor before actually calling the function.
the explicit keyword prevents that from happening; it tells the compiler that you only want that constructor run when you specifically call it.
2) in between the prototype of the constructor and its body, you can (and, for the most part, should) provide an initializer list; When a constructor is run, the system initializes every parent, then every contained member before running the body of the constructor. The initializer list tells the compiler which constructor you want to be run on a given member variable; in the case of your example, you're running the copy constructor on typeId.
If you don't provide an entry in the initializer list for a given member, the system will simply run the default constructor on that member before entering the body of the original class. This means that, should you assign to the member within the body of your class constructor, you'll be writing to that member's memory twice. This is necessary sometimes, but for many cases is simply wasteful.
3) const at the end of a method prototype makes a guarantee to the compiler that that method will not modify any of the member variables within the class instance when it is called. This allows the method to be called on const instances of your class, and, just like placing const on any variables that will remain unchanged, should be done whenever possible to guarrantee correctness and type safety.
As for which books to read, the link in your question's comments would be a good place to start. Since you seem to understand the barebones basics of the language, I would recommend starting with "Effective C++". It presents a list of best practices for C++, and is aimed at someone who understands the C aspects of the language.