Multiple constructors in C++ - c++

Question is about multiple constructors that confuses me.
#include "complex.h"
#include <iostream>
using namespace std;
Complex::Complex(double realPart, double imPart)
: m_R(realPart), m_I(imPart)
{
cout << "complex(" << m_R << "," << m_I << ")" << endl;
}
Complex::Complex(double realPart)
{
Complex(realPart, 0);
}
Complex::Complex() : m_R(0.0), m_I(0.0)
{
}
int main() {
Complex C1;
Complex C2(3.14);
Complex C3(6.2, 10.23);
}
Can someone explain how compiler knows which constructor to use of three defined? Primer is from this book, page 58.

Side Note
If you want to utilize C++ 11 delegating constructors you should write:
Complex::Complex(double realPart)
: Complex(realPart, 0)
{}
instead of
Complex::Complex(double realPart) {
Complex(realPart, 0);
}
which creates a temporary unused Complex inside the constructor body.

It depends on the number and types of arguments supplied to the constructor. Thus
std::Complex first(1, 2.0); // Use first constructor
std::Complex second(5.0); // Use second constructor
std::Complex third; // Use third constructor with no arguments.

Related

emplace and try_emplace with copy constructor

I have an issue with emplace and try_emplace as they always use the copy constructors when moving an object in.
#include <iostream>
#include <unordered_map>
#include <map>
using namespace std;
class Too {
public:
Too(int x, int y):x_(x), y_(y) {
cout << "init " << x_ << endl;
}
Too(const Too& too):x_(too.x_+1), y_(too.y_+1) {
cout << "Copy happen: x = " << x_ << endl;
}
~Too() {
cout << "delete too " << x_ << endl;
}
private:
int x_, y_;
};
std::map<int, Too> v;
int main()
{
v.emplace(100, Too{ 100,23 });
v.try_emplace(12, 12, 13);
Too t = Too(10, 11);
v.try_emplace(11, std::move(t));
}
output
init 100
Copy happen: x = 101
delete too 100
init 12
init 10
Copy happen: x = 11
delete too 10
delete too 101
delete too 12
delete too 11
As you can see, only v.try_emplace(12, 12, 13) do not use the copy constructor.
both v.emplace(100, Too{ 100,23 }) and v.try_emplace(11, std::move(t)) invoke the copy constructor.
So how can it be even when I use std::move(t)?
Any suggestion would be highly appreciated.
Thanks,
Since you've provided a copy constructor for your class, the move constructor Too::Too(Too&&) will not be implicitly generated by the compiler.
Moreover, when there is no move constructor available for a class, the copy constructor can be used.
For using the move constructor you have to explicitly provide an appropriate user-defined move constructor Too::Too(Too&&), then you will get the desired result.
You can add the move constructor either by adding Too(Too&&) = default; or writing your own move constructor which will do the initialization in the constructor initializer list.

Operator overloading (object addition)

#include "stdafx.h"
#include "iostream"
using namespace std;
class complex
{
int real;
int img;
public:
complex(int x = 0, int y = 0)
{
cout << "Inside Prama" << endl;
real = x;
img = y;
}
complex operator+(complex x)
{
complex temp;
temp.real=real + x.real;
temp.img=img + x.img;
return temp;
}
void display()
{
cout << real << ' ' << img << endl;
}
};
int main()
{
class complex c1(5,6), c2(7,8),c3(7,7),c4;
c1.display();
c2.display();
c3.display();
c4 = c1+c2+c3;
c4.display();
return 0;
}
for above operator overloading code following is the output:
why that parameterized constructor is called at the time of adding of the objects.I am not getting the reason for that
Just summarizing comments...
Here
complex operator+(complex x)
{
complex temp;
temp.real=real + x.real;
temp.img=img + x.img;
return temp;
}
complex temp; calls the constructor and thats the output you see. Typically you'd pass x as const reference to avoid the copy, but as you need a copy anyhow you can use x:
complex operator+(complex x)
{
x.real +=real;
x.img +=img;
return x;
}
This will only invoke the compiler generated copy constructor when you call the operator.
There are more subtleties to consider. Using x instead of making a local copy inhibits named return value optimization. Also it is common to implement operator+ in terms of operator+= and operator+ can be a free function then. Note that operator+= can be more efficient, because no copy is needed at all. For more details on operator overloading in general I refer you to What are the basic rules and idioms for operator overloading?
PS: "parametrized constructor" is a term I have seen only in poor misleading tutorials so far. It is not an official term. The relevant term here is default constructor. complex(int x = 0, int y = 0) is a default constructor because it can be called without parameters. It is a good example for why "parametrized constructor" does not convey lots of meaning and is rather misleading.

No matching Function for a call [duplicate]

This question already has answers here:
What are all the member-functions created by compiler for a class? Does that happen all the time?
(5 answers)
Closed 6 years ago.
I've created very simple C++ project in codeblocks. I have header file (CVector.h), source file (CVector.cpp) and main code (code.cpp). When I try to compile the code I got the following message:
CVector.cpp|22|error: no matching function for call to 'CVector::CVector()'|
code.cpp
#include <iostream>
#include "CVector.h"
using namespace std;
int main () {
CVector vec1(1,2);
CVector vec2 (3,4);
cout << "vec1 data "; vec1.printData();
cout << "vec2 data "; vec2.printData();
cout << "vec1 area: " << vec1.area() << endl;
cout << "vec2 area: " << vec2.area() << endl;
return 0;
}
CVector.h
#ifndef CVECTOR_H
#define CVECTOR_H
class CVector
{
int x,y;
public:
CVector (int, int);
int area();
void printData ();
CVector operator+ (CVector param );
};
#endif // CVECTOR_H
CVector.cpp
#include <iostream>
#include "CVector.h"
using namespace std;
CVector::CVector (int a, int b) {
x=a;
y=b;
}
int CVector::area() {return x*y;}
void CVector::printData(){
cout << "X = " << x << ", Y = " << y << endl;
}
CVector CVector::operator+ (CVector param )
{
CVector temp;
temp.x=x + param.x;
temp.y=y + param.y;
return temp;
}
The error is related to the operator overloading function because it compiles without problems when I comment this function.
In operator+, the line
CVector temp;
needs a default constructor, but you didn't define one.
(If you define a non-default constructor, the compiler will not provide a default one.)
You can either define a default constructor, if you can decide on what suitable default values of the members could be, or you can write
CVector CVector::operator+ (CVector param )
{
CVector temp(x + param.x, y + param.y);
return temp;
}
or even
CVector CVector::operator+ (CVector param )
{
return CVector(x + param.x, y + param.y);
}
The problem in you operator + is this line:
CVector temp;
This lines creates a default-constructed CVector. However, your CVector class does not have a default constructor, hence the error. You need to add one to the class:
class CVector
{
int x,y;
public:
CVector(); // Added
//The rest as before
};
There are two ways to implement it. One:
CVector::CVector() {}
This will result in the members x and y remaining uninitialised.
Two:
CVector::CVector() : x(0), y(0) {}
This will initialise x and y to 0.
The second one is safer, the first one is faster. Which one to use depends on your goals for the class.
Unrelated, but in your two-parameter constructor, you should use the member initialisation list instead of assignments as well:
CVector::CVector(int a, int b) : x(a), y(b) {}
It doesn't really matter for primitive types such as int, but it's a good habit to grow. It's more efficient for members of a type with a nontrivial default constructor, and is actually nceessary for members of a type without a default constructor.

Compiler Optimization of copy construction?

The following code:
#include <iostream>
using namespace std;
struct A {
A(int a) { cout << "cast "; }
A(const A& a) { cout << "copy " ;}
};
int main () {
int x = 0;
A a = x;
return 0;
}
gives the output cast, while I expected the output to be: cast copy.
Is it a compiler optimization, or a simple misunderstanding of what's going on?
Thanks in advance!
An implicit conversion from int to A through the constructor A(int i) is happening over here.
So, I guess, compiler does some optimization.
If you use explicit keyword for first constructor, it won't compile.

Uniform initialization syntax difference

What's the difference between doing
A a{ A() };
and,
A a( A{} );
to avoid the Most Vexing Parse? When should I use a particular one?
The two syntaxes are equivalent in most situations, and which one to choose is mostly a matter of taste. If you are into uniform initialization, I would suggest doing:
A a{ A{} };
Otherwise, parentheses alone can be used to disambiguate:
A a((A())); // This can't be parsed as a function declaration
Notice, that there is one situation (very unlikely, I must say) where the two forms shown in your question are not equivalent. If your class A has a constructor that takes an initializer_list<A>, that constructor will be favored over the copy constructor when the braces are used:
#include <initializer_list>
#include <iostream>
struct A
{
A() { }
A(std::initializer_list<A> l) { std::cout << "init-list" << std::endl; }
A(A const& a) { std::cout << "copy-ctor" << std::endl; }
};
int main()
{
A a(A{}); // Prints "copy-ctor" (or nothing, if copy elision is performed)
A b{A()}; // Prints "init-list"
}
The above difference is shown in this live example.
In most situations they are equivalent, but A a{ A() }; will prefer a std::initializer_list constructor if one is present, while A a( A{} ); will prefer a move/copy constructor.
When the construct ends up calling a move/copy constructor, the construction of the new object can be elided, but this is not possible for a std::initializer_list constructor.
Neither syntax will ever be parsed as a function declaration, so both avoid the most-vexing-parse.
#include <iostream>
#include <initializer_list>
struct A {
A() {
std::cout << "A()\n";
}
A(A&&) {
std::cout << "A(A&&)\n";
}
A(std::initializer_list<A>) {
std::cout << "A(std::initializer_list<A>)\n";
}
};
int main()
{
{A a{ A() };} // Prints "A()\n" "A(std::initializer_list<A>)\n"
{A a( A{} );} // Prints "A()\n" and *possibly*
// (depending on copy elision) "A(A&&)\n"
}