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.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have to understand why this program in C++ isn't working. There were many other errors but I corrected them.
#include <iostream>
using namespace std;
class X {
public :
X(int a) : a(a) {}
virtual void f(ostream& flot) const { flot << " X::f" << endl; }
virtual void g() const = 0;
private :
int a;
};
class Z : public X {
void h() const {cout << "Z::h" << endl;}
public :
Z() : X(0) {}
void f(ostream& flot) const override { flot << "Z::f" << endl;}
void g() const override {cout << "Z::g" << endl;}
};
void operator<< (ostream& flot, const Z& z ) { z.f(flot);}
int main() {
Z z;
cout << z << endl;
Z z2();
z2.h();
X* x1;
x1->f(cout);
z.h();
}
You can't write cout << z << endl; because z does not exist as a normal object, is it correct? it is a kind of imaginary object ? at the contrary of z2 which is constructed and does exists. Can you tell me if I am right?
And I don't understand why the two last lines:
x1->f(cout);
z.h();
are not problematic. I thought that x1 does not exists (as z). So why can you call a method for x1?
And for z.h(), the only problem is that h is, here, in this context, private. But if it would have been inside the public part, it wouldn't be a problem. Why ??? Isn't z imaginary so you can't use any method on it?
Z z;
This defines and constructs an object z of type Z. The default constructor is called.
cout << z << endl;
This calls operator<< for (cout, z), and then uses the return value of that to call operator<< for it and endl. The return value is void, so the second call cannot work. Your operator<< needs to return the output stream for this to work.
Z z2();
This defines a function z2 that takes no arguments and returns a Z. Not a variable, but not actually wrong itself.
z2.h();
At this point it's wrong, because z2 is a function and not an object. Try removing the parentheses, or changing the previous line to Z z2 = Z();.
X* x1;
This defines a variable x1 of type X*. It's uninitialized.
x1->f(cout);
This calls the function X::f on your uninitialized pointer, which is undefined behaviour. Read undefined behaviour as "could do anything, avoid".
z.h();
This tries to call the function h on z, but it's a private function. You'll get a compile error because it's private and not accessible from main context.
To get cout to accept a Z object after the operator <<, overload the operator << to recognize an ostream object on the left and a Z on the right. The overloaded << operator function must then be declared as a friend of class Z.
The first error is solved by adding the following declaration to Z class:
friend ostream& operator<<(ostream& os, const Z& z);
On the other hand, if you want to invoke the method h on the instance z2 you have to make h public method, in your code it is private by default.
As a final note, you should receive a segmentation fault at the sentence:
x1->f(cout);
because the pointer x1 point to a non-allocated object.
There is no "imaginary" object in C++. Either an object is created or it is not. There is nothing wring with Z z;. Since the object exists, there is no problem in using the function Z::h() once you make it public.
Z z2(); doesn't create an object as you intend, since it is parsed as a function taking no argument and returng an object of Z. This is, as pointed out in the first comment, the case of most vexing parse.
Regarding the cout, the operator << should be able to print stuff from your class. Hence, you need to make the operator a friend of your class.
Also, since x1 is declared but not initialized, you will have undefined behavior for x1->f();. Also, you can't even do something like X* x1 = new X(0); because X::g() is pure virtual, and the class X is an abstract base class.
The following code would run wothout issues:
#include <iostream>
using namespace std;
class X {
public :
X(int a) : a(a) {}
virtual ~X() {}
virtual void f(ostream& flot) const { flot << " X::f" << endl; }
virtual void g() const {};
private :
int a;
};
class Z : public X {
public :
Z() : X(0) {}
void f(ostream& flot) const override { flot << "Z::f" << endl;}
void g() const override {cout << "Z::g" << endl;}
void h() const {cout << "Z::h" << endl;}
friend ostream &operator<<(ostream &os, const Z &z);
};
ostream& operator<< (ostream& flot, const Z& z ) { z.f(flot); return flot;}
int main() {
Z z;
cout << z << endl;
//Z z2();
//z2.h();
X * x1 = new X(0);
x1->f(cout);
z.h();
delete x1;
return 0;
}
I am quite new in C++ programming, so maybe that's why I can't figure out why this assignment is not working.
In my class, I want to overload "=" operator.
I have specified a function, that outputs variables as an array. In overloading, I want to assign those variables to new object.
obj_new = obj_with_variables
overloading:
obj_new_x=obj_with_values_parameters()[0];
obj_new_y=obj_with_values_parameters()[1];
Here is a code:
// Test1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "string"
using namespace std;
class Vector2D
{
public:
Vector2D()
{
}
Vector2D(int& a, int& b)
:x(a), y(b)
{
}
void Drukuj()
{
cout << "wektor [" << x << ',' << y << "] \n";
}
void Wspolrzedne(int&a, int&b)
{
x = a;
y = b;
}
int* Wspolrzedne()
{
int tab[2] = { x,y };
return tab;
}
void operator = (Vector2D& obj)
{
int* a = obj.Wspolrzedne();
cout << a[0] << "\n";
x = a[0];
cout << x << " what? \n";
y = a[1];
}
private:
int x, y;
};
int main()
{
int x1 = 2, x2 = 3;
Vector2D wektor(x1, x2);
wektor.Drukuj();
Vector2D wektor2;
wektor2 = wektor;
wektor2.Drukuj();
wektor.Drukuj();
return 0;
}
The problem is that it assigns some strange values. However, if I don't use a reference, but declare 2 int values (j,k) and assign array element to them [0,1], it works fine.
Also, when using static numbers (for example, instead of a[0] ; use "2") it works fine too.
What is going on?
I would be glad if somebody could point me to right answer/ resources.
Regards,
In your member function int* Wspolrzedne(), you return the address of local variable tab. Accessing this variable once its life time has ended, as you do in your = operator, is undefined behaviour.
Your code has undefined behavior because operator= is accessing invalid data. Wspolrzedne() is returning a pointer to a local variable tab that goes out of scope when Wspolrzedne() exits, thus the a pointer used in operator= is not pointing at valid data.
If you want Wspolrzedne() to return multiple values, you need to have it return (by value) an instance of a struct or class to hold them. Try something more like this:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
struct Coordinate {
int x;
int y;
};
class Vector2D
{
public:
Vector2D()
: x(0), y(0)
{
}
Vector2D(int a, int b)
: x(a), y(b)
{
}
Vector2D(const Coordinate &c)
: x(c.x), y(c.y)
{
}
Vector2D(const Vector2D &src)
: x(src.x), y(src.y)
{
}
void Drukuj()
{
cout << "wektor [" << x << ',' << y << "] \n";
}
void Wspolrzedne(int a, int b)
{
x = a;
y = b;
}
void Wspolrzedne(const Coordinate &c)
{
x = c.x;
y = c.y;
}
Coordinate Wspolrzedne()
{
Coordinate c = { x, y };
return c;
}
Vector2D& operator=(const Vector2D &obj)
{
Coordinate c = obj.Wspolrzedne();
cout << c.x << ',' << c.y << "\n";
Wspolrzedne(c);
return *this;
}
private:
int x;
int y;
};
On the other hand, there is no real reason to even have operator= call Wspolrzedne() to get the coordinates at all, when it can just access obj.x and obj.y directly instead:
Vector2D& operator=(const Vector2D &obj)
{
x = obj.x;
y = obj.y;
return *this;
}
In which case, you can simply eliminate your operator= altogether, and let the compiler provide a default-generated implementation that does the exact same thing for you.
Your interface is dangerous, as returning raw pointers from functions means the caller must know how to manage it. That is, the caller needs to be astutely aware of the answers to questions like, "should the caller delete the pointer or does the object I got it from retain ownership?" What is this pointer pointing to? If it's an array, now many elements are there? If I must delete it, do I use delete or delete[]?
And so on. This is not good because it's very, very error prone.
Next you have a function that returns a pointer to stack-local data. When the function returns, that memory is already invalid so the return value is always going to result in undefined behavior to read.
int* Wspolrzedne()
{
int tab[2] = { x,y };
return tab; // BAD - returns pointer to function stack data
}
Where does tab live? It's destroyed when the function exits, but you're returning a pointer to it.
This is a dangerous interface and should be changed. Perhaps you should return the values as a pair:
std::pair<int, int> Wspolrzedne()
{
return std::pair{ x,y }; // assuming c++17
// return std::pair<int, int>{x, y}; // older compilers
}
An interface like this avoids pointers, and removes all the issues mentioned above.
I'm self-learning C++ as a beginner, and I faced some problems regarding Nested Classes. I was trying to define a class for a quadrangle given four vertices (define a point called vertices), which
is represented by an object of a nested class for two-dimensional points. I only use one point to test my answer. My answer to the question is:
#include <iostream>
#include <assert.h>
using namespace std;
class quadrangle
{
public:
class vertex
{
private:
public:
int x, y;
friend class quadrangle;
vertex();
vertex(int a, int b);
vertex(const vertex & old);
};
vertex p1;
int a, b;
friend class vertex;
quadrangle();
quadrangle(vertex(int a, int b)) : p1(a,b) {};
quadrangle(const quadrangle & old);
void draw();
};
quadrangle::vertex::vertex()
{
x = 0; y = 0;
}
quadrangle::vertex::vertex(int a, int b)
{
x = a; y = b;
}
void quadrangle::draw()
{
cout << "p1: (" << p1.x << "," << p1.y << ") " << endl;
}
quadrangle::quadrangle()
{
p1.x = 0; p1.y = 0;
}
int main()
{
quadrangle q1(quadrangle::vertex(2,3));
q1.draw();
}
Somehow I just got
error: no matching function for call to
'quadrangle::quadrangle(quadrangle::vertex)'
and have stuck for a whole afternoon. Could someone explain what's wrong in my code?? I know something's wrong with my constructor but I just couldn't fix it...
Following is not what you expect:
quadrangle(vertex(int a, int b)) : p1(a,b) {};
it is a constructor which take a function returning vertex and taking 2 int.
and then you initialize member vertex p1 with uninitilized member a and b.
What you want is simply:
quadrangle(const vertex& v) : p1(v) {}
(And remove members a, b).
Your error tell it all, you dont have constructor:
quadrangle(const vertex & old);
and it is required to make this initialization:
quadrangle q1(quadrangle::vertex(2,3));
And this is really strange:
quadrangle(vertex(int a, int b)) : p1(a,b) { }
it looks like its a constructor taking a function prototype (or a function type?) - but its not a function pointer I guess. p1(a,b) compiles only because you have such variables in your class.
[edit]
after comment from Quentin - above declaration is a function pointer
Function types in a function parameters' declaration decay to pointers
below example shows various ways you can write function pointer as parameter to function:
std::string bar(int a, int b) {
std::cout << "bar";
return "";
}
void foo1(std::string(int a, int b)) { } // Unnamed function pointer
void foo2(std::string(pf)(int a, int b)) { pf(0,0); } // Named function pointer
void foo3(std::string(*pf)(int a, int b)) { pf(0,0);} // Named function pointer
int main() {
foo1(bar);
foo2(bar);
foo3(bar);
}
I am trying to understand the order of exectution of a class which has nested objects of another class inside it. Here's my simple program :
#include<iostream>
#include <string>
using namespace std;
class Alpha
{
int a;
public:
Alpha(int x)
{
a=x;
}
};
class Beta
{ int b;
public:
Beta(int y)
{
b=y;
}
};
class Gamma
{
Alpha A;
Beta B;
int c;
public:
Gamma(int a,int b, int d): A(a), B(b)
{
c=d;
}
};
void main()
{
Gamma g(5,6,7);
}
As you can see, Gamma has 2 nested objects. Now when the first line of main() is executed, how does the execution start inside the class Gamma? The constructer is called first or the objects/data-members are created first?
The question of constructor execution order is simple: first, Gamma constructor starts, but then it immediately proceeds to initializing Alpha and Beta, as specified in your initialier list. Once the intializer list is done, the body of Gamma's constructor is executed.
There is an important twist to this: C++ will initialize nested objects in the order in which they are declared in the class, not in the order in which they are listed in the initializer list. In other words, Alpha will be initialized ahead of Beta even if you reverse A(a) and B(b):
// The compiler will issue a warning for this
Gamma(int a,int b, int d): B(b), A(a)
{
c=d;
}
The constructer is called first or the objects/data-members are created first?
From an initializer list the members or base class constructor calls are executed before the constructors body of the containing / inherited class.
You can easily check what's going on placing some output statements in the constructors
Alpha(int x) {
cout << "a = " << a << std::endl;
a=x;
cout << "Alpha(" << a << ")" << std::endl;
}
Beta(int y) {
cout << "b = " << b << std::endl;
b=y;
cout << "Beta(" << b << ")" << std::endl;
}
Gamma(int a,int b, int d): A(a), B(b) {
cout << "c = " << c << std::endl;
c=d;
cout << "Gamma(" << c << ")" << std::endl;
}
Output is
a = 0
Alpha(5)
b = 134514731
Beta(6)
c = -1218371596
Gamma(7)
See here for a fully working sample.
Objects in the initialization list are initialized first. Then, the body of the constructor inside {} is executed.
Here's a program, where I am trying to call the class constructor multi::multi(int, int), in the function void multi::multiply(). The output is
30
30
instead of expected
30
25
Why?
#include <iostream.h>
class multi{
private:
int a;
int b;
public:
multi(int m, int n){
a = m;
b = n;
}
void multiply(){
cout << "\n\n" << a*b;
multi (5, 5);
cout << "\n" << a*b;
}
};
main(){
multi x(5,6);
x.multiply();
return 0;
}
multi (5, 5);
It creates a temporary object, and gets destroyed by the end of the full expression. It doesn't do multiplication or printing.
To see the desired output, you can add a reset() member function to your class:
class multi{
private:
int a;
int b;
public:
multi(int m, int n) : a(m), b(n) {} //rewrote it
void reset(int m, int n) { a = m; b = n; } //added by me
void multiply(){
cout << "\n\n" << a*b;
reset(5, 5); //<-------------- note this
cout << "\n" << a*b;
}
};
By the way, prefer using member-initialization-list when defining constructors.
When you're calling the constructor multi(5, 5) you're actually creating a temporary object that is immediately destructed.
This doesn't work, because multi(5, 5); creates a temporary object of class multi, which is immediately destroyed, because it is not used for anything
Since multiply() is a member function of class multi, it has access to the private members, so it can just set a and b directly. You can get your expected output by rewriting multiply like this:
void multiply()
{
cout << "\n\n" << a*b;
b = 5;
cout << "\n" << a*b;
}
You can't call constructors like this. What your code does is create a new temporary instance of multi, which gets discarded immediately.
Once an object is constructed, you can't call its constructor again. Create an assign() function or something similar in your class.
You can't call a constructor of an already created object. What you are doing in code is, creating a temporary object.
Compiler will report error if you do try to do
this->multi(5,5).