Initialization of member variable via parentheses doesn't work [duplicate] - c++

This question already has an answer here:
Why class data members can't be initialized by direct initialization syntax?
(1 answer)
Closed 11 months ago.
For the following codes, can anyone explain why we can't initialize the variable data by parentheses?
#include <iostream>
using namespace std;
class X
{
private:
int data(1); // wrong here
public:
void print()
{
cout << data << endl;
}
};
int main()
{
X temp;
temp.print();
return 0;
}

There isnt actually much to explain, its just not valid syntax. Default member initializers are
class X
{
private:
int data{1}; // ok
int data2 = 42; // also ok
public:
void print()
{
cout << data << endl;
}
};
While int data(1); is not valid syntax for a default member initializer. See here for details: https://en.cppreference.com/w/cpp/language/data_members

Related

set default parameter to a member variable [duplicate]

This question already has answers here:
How to use a member variable as a default argument in C++?
(4 answers)
Closed 1 year ago.
I tried to set a default parameter to a member variable, it gave me this bug.
[cquery] invalid use of non-static data member 'num'
code
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int num = val){
std::cout << num << '\n';
}
}
int main(){
Test test;
test.print_num();
return 0;
}
Despite it being quite obvious what this would mean, you just can’t. The usual workaround is to provide an overload that (implicitly) uses this to get the member value.
In order to set a default value for a function parameter to a class member, the member must be static.
Citing the documentation,
Non-static class members are not allowed in default arguments
However, given the context of your code sample I doubt this is what you want to do (as every instance of Test class will point to the same val. Citing the docs:
Static members of a class are not associated with the objects of the class: they are independent variables
If you make val static in your example, and have multiple instances of Test in use by your code, you can (and very likely will) have some unexpected behavior. Consider:
#include <iostream>
class Test{
private:
static int val;
public:
void print_num(int num = val){
std::cout << num << '\n';
}
void set_val(int num) {
val = num;
}
}
int Test::val = 0;
int main(){
Test test1;
test1.set_val(1);
Test test2;
test2.set_val(2);
test1.print_num(); // results in "2"
return 0;
}
A better alternative would be to pass a pointer to your function like this:
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int* numptr = nullptr){
int num = (numptr ? *numptr : val);
std::cout << num << '\n';
}
}
int main(){
Test test;
test.print_num();
return 0;
}
Or, as described by Davis Herring, use an overload:
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int num){
std::cout << num << '\n';
}
void print_num() {
return print_num(val); // return is irrelevant here, but my preferred coding style
}
}
int main(){
Test test;
test.print_num();
return 0;
}
Edited to reflect the comment and example.
Your function definition doesn't actually know what val is because it doesn't actually live inside of your class. The compiler is actually making a function that contains your class as a parameter and abstracts away all of that. You'll want to set num to val within the function body.

About constructor overload of a class template [duplicate]

This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
Closed 3 years ago.
now I am just really new to C++, currently I have a piece of code below:
#include <iostream>
using namespace std;
template<typename T>
class Test1
{
public:
Test1():var1(1) {
cout << "Constructor1" << endl;
}
Test1(T a):var1(a) {
cout << "Constructor2" << endl;
}
private:
int var1;
};
template<typename T>
class Test2
{
public:
Test2():var2(x) {
cout << "Constructor3" << endl;
};
private:
int x;
Test1<int> var2;
};
int main()
{
Test2<int> var3;
return 0;
}
The output will just be
Constructor2
Constructor3
I wonder why the constructor2 will be called instead of constructor1, since in the class Test2, when creating the object var2, I didn't pass in any parameters, shouldn't the constructor without parameter being called?
Thank you in advance!
The constructor for a variable is determined by its initialization. You have an initialization list on your Test2 constructor
Test2():var2(x) {
so you have to look there for how Test2::var2 is initialized. In the initialization list, you're passing the integer x (that's not initialized to anything), so it calls the Test1 constructor that takes an integer.
If you don't explicitly initialize var2 in your initializer list (for example, if you just assign to it in the constructor body), then it will be default initialized and say "constructor 1" instead of 2

Aggregate Initialization of struct with dependent fields [duplicate]

This question already has answers here:
Is it defined behavior to reference an early member from a later member expression during aggregate initialization?
(4 answers)
Closed 4 years ago.
Is it legal to do the following?
#include <iostream>
struct Foo
{
int bar;
int baz;
};
int main()
{
Foo instance = { 5, instance.bar };
std::cout << instance.baz << std::endl;
}
I think it's not because as far as I know the order of initialization is unspecified and the bar field can be initialized after baz.
Am I right?
https://coliru.stacked-crooked.com/a/ea97713515dd0687
If you liked your conundrum, this is really gonna bake your noodle:
#include <iostream>
struct Foo
{
int bar=0;
int baz=1;
};
const int cool(const Foo& f)
{
std::cout << "Bar: " << f.bar << " Baz: " << f.baz << std::endl;
return f.bar;
}
int main()
{
Foo instance = { 5, cool(instance) };
std::cout << instance.baz << std::endl;
}
What a previous poster correctly quoted: c++ std draft doc
...all value computations and side effects associated with a given element are sequenced before those of any element that follows it in order.

(C++) why static member can be used before it is initialized? [duplicate]

This question already has answers here:
When are static C++ class members initialized?
(7 answers)
Closed 4 years ago.
I write this test code:
#include <iostream>
using namespace std;
class Date {
int d;
int m;
int y;
public:
static Date default_date;
public:
Date(int d, int m, int y) {
default_date.display();
this->d = d ? d : default_date.d;
this->m = m ? m : default_date.m;
this->y = y ? y : default_date.y;
}
void display() { std::cout << d << "-" << m << "-" << y << std::endl; }
};
Date Date::default_date(25, 12, 2018);
int main() {
Date d = Date(0, 0, 0);
d.display();
Date::default_date.display();
}
and the output is:
0-0-0
25-12-2018
25-12-2018
25-12-2018
OK, here is my question.
The static member default_date is initialized outside the class definition and using the constructor of class.
However, when the constructor is called, it seems that default_date already exists. I even execute default_date.display() and get the output 0-0-0.
Why I can visit default_date before it is constructed/initialized?
The first time the constructor is called is the point of initialization of default_date. And inside this constructor, before the members are assigned their supposed values, the constructor constructor calls display(), which prints zero-initialized values of the members.

What's the output of the following code? [duplicate]

This question already has answers here:
Why does this call the default constructor?
(3 answers)
Closed 9 years ago.
This code was published in http://accu.org/index.php/cvujournal, Issue July 2013.
I couldn't comprehend the output, any explanation would be helphful
#include <iostream>
int x;
struct i
{
i() {
x = 0;
std::cout << "--C1\n";
}
i(int i) {
x = i;
std::cout << "--C2\n";
}
};
class l
{
public:
l(int i) : x(i) {}
void load() {
i(x);
}
private:
int x;
};
int main()
{
l l(42);
l.load();
std::cout << x << std::endl;
}
Output:
--C1
0
I was expecting:
--C2
42
Any Explanation ?
i(x); is equivalent to i x;, with a redundant pair of parentheses thrown in. It declares a variable named x of type i, default-initialized; it does not create a temporary instance of i with x as the constructor's parameter. See also: most vexing parse