This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
Closed 4 years ago.
I am going through the "Getting started with the Windows API" portion of MSDN, and ran into an aspect of C++ I'm having trouble understanding.
I've been looking in "The C++ Programming Language" by Stroustrup, and can't find this particular thing.
Please check the link to the relevant page on MSDN.
The line that I don't understand is:
BaseWindow() : m_hwnd(NULL) { }
This line is in the latter code snippet describing an object oriented approach to the subject. m_hwnd is of the type HWND.
I really have no idea what is happening here. I'm pretty sure it's a constructor that doesn't do much of anything, but this specific syntax is foreign to me. I must admit my C++ knowledge is mostly just "C with some C++ stuff added". I'm currently diving deep into Stroustrup to remedy that.
The colon is just a syntax divider between the constructor declaration and the constructor initializer list.
It's a way to directly construct (or initialize) member variables.
It's similar (but not equal) to
BaseWindow()
{
m_hwnd = NULL;
}
Another way to look at it: Lets say you define a normal local variable, and want to initialize it to a specific value. There are a couple of ways to doing it.
Definition (with default initialization) and assignment:
HWND hwnd;
hwnd = 0;
Definition and copy initialization:
HWND hwnd = 0;
Definition and direct initialization:
HWND hwnd(0);
With a constructor initializer list, you use direct initialization in the constructor, and it happens before the constructor function body is executed.
Note that templates doesn't play any part of this. And neither does inheritance, even though it's possible to "call" a parent class constructor using a constructor initializer list.
Lastly an important note: Constructor initializer lists should not be confused with std::initializer_list.
BaseWindow() : m_hwnd(NULL) { }
That declares a default constructor for BaseWindow, which initializes the m_hwnd with a NULL value.
It does not, however, guarantee that m_hwnd will always be initialized to NULL. For instance, the default copy constructor will not do that. An explicit copy constructor is not likely to do it, either.
Related
This question already has answers here:
delete modifier vs declaring function as private
(4 answers)
Closed 3 years ago.
I have seen a lot of books recommend using =delete, is this just clear what it means? (making the program more readable) rather than saying that it is a bad thing to set the copy constructor to private?
Thinks your answers
class A {
A(const A&);
// some functions and variable
public:
// or you can A(const A&)=delete;
// do something
};
This is a relatively new functionality (added in the 2011 revision of C++) whose main motivation surely was readability and clarity of intent. However, the difference is more than just cosmetic.
Remember that with a constructor declared in the class, nothing prevents some other translation unit from actually providing the definition. It is quite usual to just list a class' member functions in a header file and implement them in a separate .cpp. If someone uses the copy constructor from inside the class, the compiler will complain that the definition is missing ("undefined reference to..."). If a naive programmer somehow reaches the conclusion that you forgot to implement it because you never needed it, they can go ahead and do so. Suddenly your class is copyable, even though only from within its own member functions (and friends). The =delete constructor prevents this, and the compiler errors are nicer (usually along the lines of "the object can't be copied because the copy constructor was declared as deleted" rather than "undefined reference to ..." or "A::A is private within this context").
This question already has answers here:
What are the advantages of list initialization (using curly braces)?
(5 answers)
Closed 1 year ago.
When I am reading The C++ Programming Language 4th Edition, to initialize a variable, the author said it's better to use {} than = to initialize a variable:
But I see that there are more people use = than {}.
So which method is a good principle to persist? = or {}?
Which one you choose depends on your own coding style and what you think is best. The most important thing is once you decide which method to use, use that method consistently. Don't switch between methods, it can make it very confusing to read your code. An additional style of variable initialization since C++98 (Called "direct initialization") is:
int variable(1)
But I would advise you against doing this, it doesn't work in certain circumstances, as your book may cover.
My personal style is the one my grandfather who worked on IBM mainframes in the 1960's taught me:
int
Variable1 = 2,
Variable2 = 39,
Variable3 = 45;
bool
Foo = true,
Bar = false;
// etc.
You'll notice I use the "=" sign over curly braces too. This seems to be how the majority of people write their code so me and my Grandfather write it that way to reduce confusion when people read our code. How accepted this method is in a corporate setting or in an organization I do not know, I simply thought it was the most attractive and intuitive style. It also saves a lot of typing.
Before any other comes up with the silly idea that
T a = b ( where b is type of T ) ends up in an assignment operator call,
Lets clear it, in C++ and in any object orient language, assignment operator can not be used on a not yet created object.
This is initialization, and this was an invoke of copy constructor all the time, was not matter of C++ version.
In this case the '=' is just a syntactic sugar.
See the Reference in the Explanation section:
The copy constructor is called whenever an object is initialized (by direct-initialization or copy-initialization) from another object of the same type (unless overload resolution selects a better match or the call is elided), which includes
initialization: T a = b; or T a(b);, where b is of type T;
One reason the book suggests using an initializer is that it becomes the initial value.
When using the assignment '=', in some cases you end up constructing the object which gives it an initial value and then the code uses the assignment operator of the class type to change the initial value, so it is less efficient. This is only in some cases, depending on the constructors available and so on.
However, in most cases modern compilers can optimize it to make it the same thing. So it's not worth worrying about.
One problem with C++ is there is always several ways to do the same thing, no matter how simple that thing may be.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is this weird colon-member syntax in the constructor?
C++ initialization
I have just received a header file in a C++ program, and I cannot figure out what this line of code does:
Card(Value faceValue=deuce, Suit suit = clubs):
suit(suit), faceValue(faceValue) {}
What does the : mean, and why does replacing it with a ; (as I thought I should) break the code?
Sorry for the generalness of this question, but could someone please explain the purpose of these two lines?
Thank you for your time.
This looks like a constructor for the Card class. The part after the : is an initializer list, initializing the values of member variables (or parent classes, but I don't think that's applicable in this case). The body of the constructor is empty because everything it needed to do was done in the initializer list.
The : and what follow is the initialization list. The reason you use it instead of assigning the member variables in the constructor's body is that if you do it inside the constructors body, the default constructor will be called first and then the copy constructor or assignment operator will be called afterwards. By using the initialization list you skip the first step.
Initialization lists. It's the preferred way to initialize class constructors in C++.
It is used because it allows the initialization of const members of the class without compilation error.
Look at this code snippet:
Size::Size(int iSetWidth, int iSetHeight)
:iWidth(iSetWidth),
iHeight(iSetHeight)
{
}
Supposedly, this means the same thing as:
Size::Size(int iSetWidth, int iSetHeight)
{
iWidth=iSetWidth;
iHeight=iSetHeight;
}
Why would you use the former or the latter? And what is the name of the former?
No, they don't mean exactly the same.
When a constructor is executed, before entering the code block (the code between the curly braces), it constructs all object data members. What you do in the initializers (the code after the colon and before the curly braces) is to specify which constructors to use for those members. If you don't specify a constructor for a specific data member, the default constructor will be used.
So, if you use the initialization list (first example), the right constructors will be used for each member and no additional code is necessary. If you don't, first the default constructor is used and then the code inside the curly braces is executed.
In summary:
In your first example, each member is initialised using the appropriate constructor, probably the copy constructor.
In your second example, each member is constructed using the default constructor, and then some additional code is executed to initialise it, probably the assignment operator.
EDIT: Sorry, forgot to answer your questions in the last line.
The name of the code between the colon and the curly braces is initialisation list.
If you know which is the right constructor for a variable or data member, by all means use it. This is the reason why most classes have different constructors instead of just a default constructor. So you are better off using the initialization list.
The initialisation list is almost never slower than the other technique, and can easily be faster. A well known rule when writing code is "don't optimize prematurely", but there is a not so well known counterpart: don't pessimize prematurely. If you have two options for writing a piece of code and one of them can be better than the other, but does not involve additional work or complexity, use it. In your example there is no difference, since you are using a built-in type (int). But if you were using classes, there would be a difference, so get used to the initialization list.
THe former is called initilazation lists.
You can get plentyof articles for that.
The particular reasons for using intializer lists are given here
http://www.learncpp.com/cpp-tutorial/101-constructor-initialization-lists/
You can refer Effective C++ to get full insight into intializer lists.
Hope it is clear.
BTW, Bjarne Stroustrup said in The C++ Programming Language that some efficiency may be gained with initialization list and he recommended us to use initialization list!
This question already has answers here:
Closed 14 years ago.
What does it mean to call a class like this:
class Example
{
public:
Example(void);
~Example(void);
}
int main(void)
{
Example ex(); // <<<<<< what is it called to call it like this?
return(0);
}
Like it appears that it isn't calling the default constructor in that case. Can someone give a reason why that would be bad?
Thanks for all answers.
Currently you are trying to call the default constructor like so.
Example ex();
This is not actually calling the default constructor. Instead you are defining a function prototype with return type Example and taking no parameters. In order to call the default constructor, omit the ()'s
Example ex;
This declares a function prototype for a function named ex, returning an Example! You are not declaring and initializing a variable here.
Does it even compile? Anyway, see this related topic.
As has been noted Example ex(); declares a function prototype. Not what anyone would expect. This C++ wart will be fixed by the new C++0x standard. In the future the preferred syntax will be Example ex{};. The new uniform construction has many other nice features, see more here.