study case in C++. Abstract class and instance [closed] - c++

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;
}

Related

Unexpected output value with class constructor and class member variable

I need to understand why x(x + 1) happened only after I get out of the constructor.
class A
{
protected:
int x;
public:
A(int x = 5) : x(x + 1)
{
cout << "In A::A x=" << x << endl;
}
operator int() const { return x; }
};
void main()
{
A a1(10);
cout << a1 << endl ;
}
I was thinking I will get:
In A:: An x=11
11
But somehow I've got:
In A:: An x=10
11
You have two variables named x.
Inside the body of the constructor the argument variable will shadow the member variable. Whenever you use x inside the body of the constructor, it will be the argument, not the member.
To use the member variable you need to explicitly fetch it from the object, like this->x.
General tip: Don't use the same name for symbols in nested scopes. Besides solving this problem, it will also make the code easier to read and understand.
Your parameter is hiding the member variable of the same name - your definition is equivalent to
class A
{
protected:
int y;
public:
A(int x = 5) : y(x + 1)
{
cout << "In A::A x=" << x << endl;
}
operator int() const { return y; }
};
When a parameter has the same name as a member, you need to explicitly refer to the member with this->.
(The initialiser list follows its own rules.)

Can't assign array element to class variable while overloading "=" operator

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.

Const member function of global variable modifying said variable via global function

The code below
#include <iostream>
class A
{
public:
int x;
double y;
A(int x_, double y_) : x(x_), y(y_)
{
}
void display(void) const;
};
class B
{
public:
static A staticObject;
};
void A::display(void) const
{
std::cout << x << ' ' << y << std::endl;
B::staticObject.x = 42;
B::staticObject.y = 3.5;
std::cout << x << ' ' << y << std::endl;
}
A B::staticObject(19, 29.3);
int main(void)
{
B::staticObject.display();
return 0;
}
prints out
19 29.3
42 3.5
and this makes me wonder:
Is it always safe to let a const member function modify the object it is called from via other means?
Further, is there any worst-case scenario that could be prevented if that member function (here display) were not declared as const?
Your code is valid and works, because display() is const but only with respect to its containing class, A. This has no impact on its ability to modify fields accessed another way--in your case via non-const public access to the two fields.
However, this code is terrible and scary.
what do you think as "safe"?
The only assumption you should make of a const member function is that it will not modify the current object it is in (this pointer). Constness though is not runtime enforced but during compilation time.
So when you "trick" your compiler with the help of static variables it cannot detect that you are actually accessing the same instance. The staticObject in B can also point to another A than the one it's being called from.
To be able to check it would require runtime checks which c++ does not do.

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.

Why is accessing private variable allowed here?

I have this class declared. I observed that in the method distance(Point b), how is it possible to access the private members of Point - b.x and b.y? If I try to access b.x and b.y in main, it is not allowed.
#include <iostream>
#include <cmath>
using namespace std;
class Point {
private:
int x, y;
public:
Point() {
cout << "Constructor called" << endl;
x = 0; y = 0;
}
~Point() {
}
void set(int a, int b) {
x = a;
y = b;
}
void offset(int dx, int dy) {
x += dx;
y += dy;
}
void print() {
cout << "(" << x << "," << y << ")" << endl;
}
// HERE
double distance(Point b) {
return (sqrt(pow(x-b.x, 2)+pow(y-b.y, 2)));
}
};
int main() {
Point p, q;
p.print();
p.offset(4, 3);
p.print();
q.set(10, 2);
cout << "Distance: " << p.distance(q) << endl;
return 0;
}
NOTE: I have compiled and ran the program on ideone.com
The concept of access specifiers such as private, public etc. applies to classes, not just objects of classes. If a variable is private in a class, and an object A of that class has a function that takes another object B of the same class, A has access to B's private members since A and B belong to the same class.
Copy constructors rely on this:
#include <iostream>
using namespace std;
class A {
public:
A(){val = 1.0;}
//copy constructor
A(const A& _other) {
val = _other.val; //accessing private member of _other
}
double dist(A _a) {return val - _a.val;} //accessing private member of _other
private:
double val;
};
int main() {
A a;
A b;
cout << a.dist(b) << endl;
}
int x, y; are private to the Class Point. It means all the members of Class Point can access,modify it.
The functions and constuctors of Class Point are public i.e Other functions(from some other class etc) [like main] can access them. The idea of OOPS is to keep your data safe, Anyone who wants to modify the values can do it via the public methods of that class. They can't access them directly. This allows you to keep any check for invalid modifications to data [setting invalid values like height = -4; etc]
If u keep int x,y as public [which is not correct OOPs] any function (main etc) can access it and modify the value to something undesirable.
Point p;
p.x = -5 (suppose you only wanted +ve values for x , you can't check if the functions accessing is setting some undesirable value)`
Not a relevant analogy , but still...You have a room in the house which only the family members can access. Any outsider who wishes to keep or remove or do anything to the things in the house has to ask your family members to do it. If u assume even family members are not allowed to access the room [assuming even member functions can't access variables ] then there is no use of keeping anythin in the room [the data cannot be used by anyone]