This question already has an answer here:
Most vexing parse
(1 answer)
Closed 9 years ago.
class A {
public:
A() { cout << "A()" << endl; }
};
class B {
public:
A a;
B(const A& a1) : a(a1) { cout << "B(const A&)" << endl; }
/* B(const A& a1) { a = a1; cout << "B(const A&)" << endl; } */
};
int main() {
B b(A()); /* no ouput */
}
No output is generated for the above code. Is that due to the compiler optimization (copy elision) as discussed in this link?
But if I have a B class constructor and re-write the code like below:
class A {
public:
A() { cout << "A()" << endl; }
};
class B {
public:
A a;
B() {}
B(const A& a1) : a(a1) { cout << "B(const A&)" << endl; }
/* B(const A& a1) { a = a1; cout << "B(const A&)" << endl; } */
};
int main() {
B().a; // gives output A()
}
add an extra pair of parentheses:
B b((A()));
// you can also fix it using new C++11 initialization syntax:
B b{A()};
the problem you are facing it called most vexing parse, and it means compiler is not able to decide whether you want a function declaration or variable definition.
[edit]
I should also add that standard requires compiler in such case to choose function declaration.
[edit]
clang is actually more helpfull in this case, and gives hint to use partentheses:
http://rextester.com/PECQ53431
source_file.cpp:16:8: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
B b(A()); /* no ouput */
^~~~~
source_file.cpp:16:9: note: add a pair of parentheses to declare a variable
B b(A()); /* no ouput */
^
( )
1 warning generated.
B b(A());
Is ambiguous and may be interpreted either as a variable declaration or as a declaration of a function that returns a restult of type B and takes a single unnamed parameter of type a function with no parameters and returns a result of type A. Although you may think first one should take place the standard dictates in fact the second one will happen. See the article about most vexing parse in wikipedia.
Instead of creating A object after B object creation, create first As object in main.
A a;
B b(a);
Related
using namespace std;
struct A
{
int i;
A(int i_ = 13) : i(i_)
{
cout << _FUNCTION_ << "\n";
}
~A()
{
cout << _FUNCTION_ << "\n";
}
};
int main()
{
A* p = new A;
A a();
return 0;
}
When I run it, the code displays on my terminal "A::A". I get that the first A is called from first FUNCTION for "A* p" , but why does "::" appear? And the last A after "::" is from " A a(); "?
A constructor for a type has the same name as the type itself. :: is the scope resolution operator and is used to name things contained within a named scope, such as a namespace or a type.
The constructor of A is therefore A::A. The first A is the name of the type, and the second is the name of the constructor; the :: is to indicate that the constructor is declared within the scope of the type.
This mirrors the way you would define type members following a declaration with no definition. For example:
struct A
{
int i;
A(int i_ = 13);
~A();
};
// Note how we have to refer to the constructor to define it since we are
// no longer within the scope of A:
A::A(int i_) : i(i_)
{
cout << _FUNCTION_ << "\n";
}
// Similar for the destructor.
A::~A()
{
cout << _FUNCTION_ << "\n";
}
You should only see A::A in your output. Note that you only create one A value here:
A* p = new A;
You never delete p; and so you don't see the matching destructor call (A::~A) in the output.
This line does not create a variable of type A; rather, it declares a function called a that takes no arguments and returns an A value. This function is never invoked (nor defined):
A a();
This is a vexing parse (not to be confused with the most vexing parse). Clearly you intended to declare a variable, but this could be either a function or variable declaration, and the grammar prefers a function declaration.
To fix this, either remove the parens or use C++11's uniform initialization syntax:
A a; // Default initialization
A a{}; // Uniform initialization
_FUNCTION_ is a magic constant, therefore it posts the first "A" (name of the function called. Can't help with the rest though.
This question already has an answer here:
C++ constructor not called
(1 answer)
Closed 4 years ago.
In my code below, I wanted to test what would happen if I had an object, that contained another object whose constructor throws exception. But the code below does absolutely nothing. Nothing is printed on the console at all.
class A
{
public:
A()
{
cout << "in A constructor" << endl;
throw "error creating A";
}
~A()
{
cout << "destructing A" << endl;
}
};
class C
{
public:
C()
{
cout <<"in C constructor" << endl;
}
~C()
{
cout << "in C destructor " << endl;
}
};
class B
{
public:
C c;
A a;
B(A a_, C c_): a(a_), c(c_){}
B(){}
};
int main()
{
try{
B b(A, C);
//B b;
}
catch(char const* s)
{
cout <<"catching" << endl;
}
}
If in the try block, I use commented code instead, then it shows fine.
I also tried doing
B b(A(), C());
Still nothing.
This is a function declaration with return type B, name b, and two unnamed arguments of type A and C:
B b(A, C);
The same for
B b(A(), C());
as names can be enclosed by parentheses (to allow grouping, necessary when working with e.g. function pointers etc.), and even names that are left out can be enclosed by parentheses. You can turn it into a variable b of type B by
B b(A{}, C{});
One of the motivation for the curly braces to initialize variables was to disambiguate in such cases. Here, it obviously comes in handy.
I have the following C++ code:
#include <iostream>
struct A
{
A() { std::cout << "A" << ++x; }
A(int x) : A() { std::cout << x; }
~A() { std::cout << "D"; }
static int x;
};
int A::x = 0;
struct B
{
A a, aa, aaa;
B() : aa(1), a(2) { std::cout << "B" << std::endl; }
~B() { std::cout << "B" << A::x; }
};
B beta;
int main()
{
return 0;
}
I understand everything in the control flow except of destructor calls.
Here is the control flow without destructors:
create object B
call constructor B
call a,aa,aaa respectively
2.1 for a, call A(int x)
2.2 for aa, call A(int x)
2.3 for aaa, call A()
display B from B c-tor body
Now the 4. step is to call destructor B, I know that.
What I don't know is what is the order of calling destructors for A.
Is it a,aa,aaa respectively, or aaa,aa,a respectively?
Thanks in advance.
The member objects get destroyed in the reversed order they got constructed. Note that you do not influence this order by changing the order in the constructor's initialization list. The order is exclusively determined by the order you declare them in the struct/class definition.
What I don't know is what is the order of calling destructors for A. Is it a,aa,aaa respectively, or aaa,aa,a respectively?
Thus, the latter case is happening.
Everything looks fine. It constructs-destructs stack-wise (First in/Last out):
#include <iostream>
struct A
{
A() { name="untitled"; std::cout << name <<" constructor" << std::endl; }
A(std::string name):name(name) { std::cout << name <<" constructor" << std::endl; }
~A() { std::cout << name <<" destructor" << std::endl; }
std::string name;
};
struct B
{
A a, aa, aaa;
B() : aa("aa"), a("a") { std::cout << "B constructor" << std::endl; }
~B() { std::cout << "B destructor" << std::endl; }
};
B beta;
int main()
{
return 0;
}
Result:
a constructor
aa constructor
untitled constructor
B constructor
B destructor
untitled destructor
aa destructor
a destructor
Is this order guaranteed? yes
If you turn on all the warnings you see this:
g++ -Wall -Wreorder main.cpp
main.cpp: In constructor ‘B::B()’:
main.cpp:12:10: warning: ‘B::aa’ will be initialized after [-Wreorder]
A a, aa, aaa;
^
main.cpp:12:7: warning: ‘A B::a’ [-Wreorder]
A a, aa, aaa;
^
main.cpp:13:5: warning: when initialized here [-Wreorder]
B() : aa("aa"), a("a") { std::cout << "B constructor" << std::endl; }
^
This took forever to find, but per n4659 (ISO C++17 draft):
15.6.2 Initializing bases and members
paragraph (13.3)
Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the
reverse order of initialization. — end note ]
Here, mem-initializers are the list following the colon in the constructor definition.
In the code below, class B has a member that is of type class A (varA1). I want to create a class B object where the member varA1 is intended to use the non-default constructor A(int v1) in class A.
#include <iostream>
using std::cout; using std::endl; using std::string;
class A {
public:
A() { cout << "A default constructor" << endl;}
A(int v1);
private:
int var1;
};
A::A(int v1) {
cout << "A int constructor" << endl;
var1 = v1;
}
class B {
public:
B() { cout << "B default constructor" << endl;}
B(int v1);
private:
int var1;
A varA1;
};
B::B(int v1) {
cout << "B int constructor" << endl;
var1 = v1;
A varA1(int v1);
}
int main()
{
A TestA(1);
B TestB(1);
return 0;
}
However when I run the code above I get the following output:
A int constructor
A default constructor
B int constructor
I must be doing some wrong here. What do I need to change so that the B class uses the non-default constructor A(int v1) in class A?
I am using ubuntu 14.04LTS. Both GNU G++ 4.9 and 5.1 gave the same results.
Thanks in advance for reading and answering.
Use a member initialization list:
B::B(int v1) : var1(v1), varA1(v1) {
cout << "B int constructor" << endl;
}
Note that members are initialized (constructed) in the same order that they're declared in the class, so switching orders in the member initialization list won't change the order in which construction happens (and hopefully your compiler will warn you of this). This little detail becomes important if you try to construct varA1 from var1 and var1 is declared after varA1 in the class definition.
And by the way, all this line does (inside the B::B(int v1) constructor):
A varA1(int v1);
is forward declare a function named varA1 that takes an int parameter and returns an A object. This is semi-similar to the most vexing parse, though this isn't really a case of the most vexing parse.
You could use an initializer list in your B::B(int) constructor:
B::B(int v1) : varA1(v1) {
cout << "B int constructor" << endl;
var1 = v1;
}
If you do not want a default ctor, you might use
A(void) = delete;
But recognize that you can temporarily add this declaration as a diagnostic measure to get the compiler to inform you for which code it wants to use the default ctor.
By replacing
A() { std::cout << "A default constructor" << std::endl;}
with
A() = delete;
The compiler will complain about the use of deleted function 'A::A()' in the body of B::B(int v1).
Thus, a brief inspection identifies that the second data attribute of B, i.e. "B::varA1", uses the default ctor of A (now deleted).
You also might consider 'fixing' the B ctor to NOT use the default ctor of A by explicitly invoking "varA1 (0)" in the initializer list of B ctor.
I'm using base-from-member idiom and I now stuck with copy/move constructors for them. Suppose following code:
#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>
using namespace std;
struct A // base class
{
A(string &s) : s(s), c(0) { };
A(const A &a) : s(a.s), c(a.c) { };
void print() { cout << s << endl; c++; }
int print_count() { return c; }
string &s;
int c;
};
struct B_base // this class will be initialized before A
{
B_base(int i)
{
s = boost::lexical_cast<string>(i);
}
B_base(const B_base &other) : s(other.s) { };
string s;
};
struct B : B_base, A // main class
{
B(int i) : B_base(i), A(B_base::s) { }
B(const B &other) : B_base(other), A(other) { } // <-- problem here
using A::print;
using A::print_count;
};
int main()
{
B b(10);
b.print(); // prints '10'
cout << b.print_count() << endl; // prints '1'
B b1(b);
b1.print(); // prints '10'
A &a = b;
a.s = "FAIL"; // we modify b, not b1 here!
b1.print(); // but b1 prints 'FAIL' here --- error (it should still print '10')
cout << b.print_count() << " " << b1.print_count() << endl; // prints '1 3'
return 0;
}
Problem here is that reference A.s (which is point to B_base::s) is copied from one instance to another, while it should be modified to point to another B_base::s. Things may be even worse, if previous instance is go out of scope ending with dangling references.
My question is: how can I make correct copy of class with base-from-member idiom? (I think move constructor will be similar to copy one, right?)
The base-from-member idiom you are exercising in this case means: you want a class B derived from A with have to be initialized using a member of B (with is: string s).
B b(10);
B b1(b); // B(const B &other) : B_base(other), A(other) { }
// now A::s in b1 is a ref to b.s
A &a = b;// and a.s is a ref to b.s too.
a.s = "FAIL"; // we modify b, and A::s in b1 to!
This problem can be solved making the copy constructor:
B(const B &other) : B_base(other), A(B_base::s) { }
Also, having A::s and B_base::s with the same name, make thing more difficult to understand.
EDIT: As a class designer, you have to decide with is the exact meaning of your copy constructor.
For example, in this case you may want to keep track (with A::c) of the number of printing of each newly create object A. The copy constructor I proposed do it.
But if you want to keep track of all printing of the original string thing are more complex. Just note that if you copy the old A::c to the new A it will be correct initialized, bur not cross actualized when the the printing of the same original string is made using different copies of A. If this is not a problem you can modify the constructors:
A(string &s, int _c=0) : s(s), c(_c) { };
...
B(const B &other) : B_base(other), A(B_base::s, other.c) { }