how to fix no viable overloaded '=' in cpp - c++

class Gebot{
string name;
int betrag;
public:
Gebot(string name, int betrag = 100) : name{name} , betrag{betrag} {
//ganze Zahl >0 und <=10.000.000
if(name.size() ==0 || betrag <=0 || betrag > 10000000)
throw runtime_error("illegal name or deposite");
}
bool selbe_bieterin(const Gebot& gebot) const{
if(gebot.name == this->name)
return true;
return false;
}
bool operator==(const Gebot& gebot) const{
name = "name";
if(gebot.betrag == this->betrag)
return true;
return false;
}
bool operator<(const Gebot& gebot) const{
if(gebot.betrag > this->betrag)
return true;
return false;
}
bool operator>=(int gebot) const{
if(gebot <= this->betrag)
return true;
return false;
}
friend ostream& operator<<(ostream& o, const Gebot & gebot){
//[Susi: 263 Euro]
o<<"["<<gebot.name<<": "<<gebot.betrag<<" Euro]";
return o;
}
};
why do I get this problemm 25:10: error: no viable overloaded '='
name = "name"; when trying to change variable name to "name". How to fix it. Thanks in advance).

This method is const
bool operator==(const Gebot& gebot) const {
^^^^^
name = "name"; <<-- changing the value of name
if(gebot.betrag == this->betrag)
return true;
return false;
}
But you are trying to change the value of name, so the code you wrote for the method is not const.
The solution would seem to be to delete the line name = "name";, it's not obvious why it is there.
BTW this code
if(gebot.betrag == this->betrag)
return true;
return false;
can be written much more simply as
return gebot.betrag == this->betrag;

Related

Input Stream Invalid read/write of size 1

i've been absolutely lost on this topic. I wrote my own String class and tried running it in valgrind to see of it really works. Valgrind tells me that i got a lot of invalid read's and write's.
Basically what im trying to do is feed it a String Value and read it's contents later on. For this i defined following Header file.
#ifndef STRING_H_INCLUDED
#define STRING_H_INCLUDED
#include<iostream>
#include<istream>
#include<ostream>
class string{
public:
string(char* = nullptr);
~string();
string(const string&);
friend std::istream& operator>>(std::istream&,string&);
friend std::ostream& operator<<(std::ostream&,string&);
bool operator<(const string&);
bool operator==(const string&);
void setContent(char*);
char* getContent() const;
private:
unsigned getSize() const;
void copyStr(char*,char*);
unsigned getCharl(const char*)const;
string& operator=(const string&);
char* s = nullptr;
};
#endif // STRING_H_INCLUDED
The CPP for the Header looks like the following.
#include<iostream>
#include<ostream>
#include "string.h"
string::string(char* i){
if(i == nullptr){
s = new char[1];
s[0] = '\0';
}else{
s = new char[getCharl(i)+1];
copyStr(s,i);
}
}
string::~string(){
if(s != nullptr){
delete s;
}
}
unsigned string::getCharl(const char* i) const{
const char* ende = i;
for(; *ende != '\0';++ende)
;
return ende-i;
}
void string::copyStr(char* s,char* i){
unsigned index = 0;
s = new char[getCharl(i)+1];
while (i[index] != '\0'){
s[index] = i[index];
index++;
}
s[index] = '\0';
}
bool string::operator<(const string& s1){
if(getSize()<s1.getSize()){
return true;
}else if(getSize()>s1.getSize()){
return false;
}else{
for(unsigned i = 0; i < s1.getSize();++i){
if(getContent()[i] != s1.getContent()[i]){
if(getContent()[i]<s1.getContent()[i]){
return true;
}else{
return false;
}
}
}
return false;
}
}
string::string(const string& x){
delete s;
s = new char[x.getSize()];
char* tmp = x.getContent();
unsigned index = 0;
while (tmp[index] != '\0'){
this->s[index] = x.s[index];
index++;
}
}
char* string::getContent() const{
return s;
}
void string::setContent(char* v){
s = v;
}
string& string::operator=(const string& x){
if(this == &x)
return *this;
if(&x != this){
delete getContent();
setContent(nullptr);
setContent(new char[x.getSize()]);
}
copyStr(getContent(),x.getContent());
return *this;
}
bool string::operator==(const string& l){
if(getSize() == l.getSize()){
unsigned length = getSize();
for(unsigned i = 0; i < length;++i){
if(getContent()[i] != l.getContent()[i])
return false;
}
return true;
}
return false;
}
std::istream& operator>>(std::istream& is, string& arg){
return is >> arg.s;
}
std::ostream& operator<<(std::ostream& os, string& arg){
return os << arg.getContent();
}
unsigned string::getSize() const{
unsigned length = 0;
while(s[length]){
++length;
}
++length;
return length;
}
Basically i would be pretty happy to know why i get an error in my operator>> where i try to write a char* Array to my char* s.
And i would like to know why i get an error in my function getSize() in the while-loop. (Error appears at s[length]).
Maybe someone is so kind to explain me the reasons.
Cheers!
Edit:
Modified the program now to look like the following implementing the comments.
#include<iostream>
#include<ostream>
#include "string.h"
string::string(char* i){
if(i == nullptr){
s = new char[1];
s[0] = '\0';
}else{
s = new char[getCharl(i)+1];
copyStr(i);
}
}
string::~string(){
if(s != nullptr){
delete[] s;
}
}
unsigned string::getCharl(const char* i) const{
const char* ende = i;
for(; *ende != '\0';++ende)
;
return ende-i;
}
void string::copyStr(char* i){
unsigned index = 0;
delete[] s;
char* tmp = new char[getCharl(i)+1];
while (i[index] != '\0'){
tmp[index] = i[index];
index++;
}
tmp[index] = '\0';
s = tmp;
}
bool string::operator<(const string& s1){
if(getSize()<s1.getSize()){
return true;
}else if(getSize()>s1.getSize()){
return false;
}else{
for(unsigned i = 0; i < s1.getSize();++i){
if(getContent()[i] != s1.getContent()[i]){
if(getContent()[i]<s1.getContent()[i]){
return true;
}else{
return false;
}
}
}
return false;
}
}
string::string(const string& x){
copyStr(x.getContent());
}
char* string::getContent() const{
return s;
}
void string::setContent(char* v){
s = v;
}
string& string::operator=(const string& x){
if(this == &x)
return *this;
if(&x != this){
delete[] getContent();
setContent(nullptr);
setContent(new char[x.getSize()]);
}
copyStr(x.getContent());
return *this;
}
bool string::operator==(const string& l){
if(getSize() == l.getSize()){
unsigned length = getSize();
for(unsigned i = 0; i < length;++i){
if(getContent()[i] != l.getContent()[i])
return false;
}
return true;
}
return false;
}
std::istream& operator>>(std::istream& is, string& arg){
is >> arg.s;
return is;
}
std::ostream& operator<<(std::ostream& os, string& arg){
return os << arg.getContent();
}
unsigned string::getSize() const{
unsigned length = 0;
while(getContent()[length]){
++length;
}
++length;
return length;
}
Still the problem with the operator>> exists and also now im getting errors in getCharl in the for loop and copyStr im the while loop. (invalid read)
If someone would be so kind and explain to me why.

Sorting with overloaded operators on a pointer array

So, to summarize, I have an array of pointers pointing to objects of class "bookType" whose operators have been overloaded and I am trying to use the selection Sort to sort them by quantity in descending order (ie 10 to 1), yet the order is seemingly random after running this code.
Selection Sort
void selectionSort(bookType *arr[BOOKS], int n){
bookType *temp;
int i, j, minIndex;
for (i = 0; i < n - 1; i++) {
minIndex = i;
for (j = i + 1; j < n; j++)
if (arr[j] > arr[minIndex])
minIndex = j;
if (minIndex != i) {
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
bookType prototype:
class bookType{
public:
bookType();
string getTitle() const;
string getAuthor() const;
string getPublisher() const;
string getDateAdded() const;
string getISBN() const;
int getQty() const;
double getWholesale() const;
double getRetail() const;
static int getBookCount();
void setTitle(string title);
void setISBN(string ISBN);
void setDateAdded(string date);
void setAuthor(string author);
void setPublisher(string publisher);
void setQty(int qty);
void setWholesale(double wholesale);
void setRetail(double retail);
static void setBookCount(int count);
bool operator==(const bookType &other);
bool operator!=(const bookType &other);
bool operator<(const bookType &other);
bool operator<=(const bookType &other);
bool operator>=(const bookType &other);
bool operator>(const bookType &other);
void operator=(const bookType &other);
private:
string bookTitle;
string bookAuthor;
string bookPublisher;
string dateAdded;
string bookISBN;
int qtyOnHand;
double bookWholesale;
double bookRetail;
static int bookCount;
};
Overloading code
bool bookType::operator==(const bookType &other){
if (getQty() == other.getQty()) return true;
else return false;
}
bool bookType::operator!=(const bookType &other){
if (getQty() != other.getQty()) return true;
else return false;
}
bool bookType::operator<(const bookType &other){
if (getQty() < other.getQty()) return true;
else return false;
}
bool bookType::operator<=(const bookType &other){
if (getQty() <= other.getQty()) return true;
else return false;
}
bool bookType::operator>=(const bookType &other){
if (getQty() >= other.getQty()) return true;
else return false;
}
bool bookType::operator>(const bookType &other){
if (getQty() > other.getQty()) return true;
else return false;
}
void bookType::operator=(const bookType &other){
setTitle(other.getTitle());
setAuthor(other.getAuthor());
setPublisher(other.getPublisher());
setDateAdded(other.getDateAdded());
setISBN(other.getISBN());
setQty(other.getQty());
setWholesale(other.getWholesale());
setRetail(other.getRetail());
}

Why it's not possible to assign std::string to a subtring?

This is the code for my project which I want to compile. The error is stated at the end of the question.
#include <iostream>
#include <string>
#include <stdio.h>
class substring {
friend std::ostream& operator<<(std::ostream& output, substring const& sub);
public:
char *str;
int length;
substring();
~substring();
substring(std::string);
substring(const substring &);
substring& operator=(substring const& other);
substring& operator=(std::string const& strz);
substring& operator+=(substring const& other);
bool operator>(substring const& other) const;
bool operator<(substring const& other) const;
char& operator[](size_t idx);
char operator[](size_t idx) const;
};
std::ostream& operator<<(std::ostream& output, substring const& sub);
std::istream& operator >> (std::istream& input, substring const& sub);
bool operator==(substring const& one, substring const& another);
bool operator!=(substring const& one, substring const& another);
bool operator==(std::string const& str, substring const& sub);
bool operator==(substring const& sub, std::string const& str);
bool operator!=(std::string const& str, substring const& sub);
bool operator!=(substring const& sub, std::string const& str);
substring::substring()
{
length = 0;
}
substring::~substring()
{
delete str;
}
substring::substring(std::string)
{
}
substring::substring(const substring & sub)
{
str = new char[length];
}
std::ostream & operator<<(std::ostream & output, substring const & sub)
{
output << sub;
return output;
}
std::istream & operator >> (std::istream & input, substring const & sub)
{
std::cout << "Enter sub:";
input >> sub;
return input;
}
bool operator==(substring const & one, substring const & another)
{
if (one.length != another.length)
return false;
else
{
for (int i = 0; i < another.length; i++)
if (one[i] != another[i])
{
return false;
break;
}
}
return true;
}
bool operator!=(substring const & one, substring const & another)
{
if (one.length != another.length)
return true;
else
{
for (int i = 0; i < another.length; i++)
if (one[i] != another[i])
{
return true;
break;
}
}
return false;
}
bool operator==(std::string const & str, substring const & sub)
{
if (sub.length != str.length())
return false;
else
{
for (int i = 0; i < sub.length; i++)
if (str[i] != sub[i])
{
return false;
break;
}
}
return true;
}
bool operator==(substring const & sub, std::string const & str)
{
if (str.length() != sub.length)
return false;
else
{
for (unsigned int i = 0; i < str.length(); i++)
if (sub[i] != str[i])
{
return false;
break;
}
}
return true;
}
bool operator!=(std::string const & str, substring const & sub)
{
if (sub.length != str.length())
return true;
else
{
for (int i = 0; i < sub.length; i++)
if (str[i] != sub[i])
{
return true;
break;
}
}
return false;
}
bool operator!=(substring const & sub, std::string const & str)
{
if (sub.length != str.length())
return true;
else
{
for (int i = 0; i < sub.length; i++)
if (str[i] != sub[i])
{
return true;
break;
}
}
return false;
}
substring & substring::operator=(substring const & other)
{
delete str;
length = other.length;
str = new char[length];
for (int i = 0; i<length; i++)
{
str[i] = other.str[i];
}
return *this;
}
substring & substring::operator=(std::string const & strz)
{
length = strz.length();
str = new char[length];
for (int i = 0; i<length; i++)
{
str[i] = strz[i];
}
return *this;
}
substring & substring::operator+=(substring const & other)
{
char* new_str = new char[length + other.length];
for (int i = 0; i<length; i++)
{
new_str[i] = str[i];
}
for (int i = length; i<other.length; i++)
{
new_str[i] = other.str[i];
}
delete str;
str = new_str;
return *this;
}
bool substring::operator>(substring const & other) const
{
return true;
}
bool substring::operator<(substring const & other) const
{
return true;
}
char & substring::operator[](size_t idx)
{
return str[idx];
}
char substring::operator[](size_t idx) const
{
return str[idx];
}
int main()
{
std::string str = "abc";
substring sub = str;
std::cout << sub;
return 0;
}
The problem is that when I run this code, it seems that the compiler just skips this: substring sub = str;.
I cannot even change this line to substring sub = "aaa"; because it shows an error which says I cannot convert subtring to std::string (although there is an operation overloading for this in the code).
The problem is that when I run this code, it seems that the compiler just skips this: substring sub = str;
The compiler did not "skip it". It compiled succesfully, and the new object was created succesfully. However, the converting constructor that you defined leaves the objects members default initialized:
substring::substring(std::string)
{
}
I cannot even change this line to substring sub = "aaa"; because it shows an error which says I cannot convert subtring to std::string
I highly doubt that. I suspect that you misread.
My compiler says that const char [4] cannot be converted substring
(although there is an operation overloading for this in the code).
There certainly isn't a substring::substring(const char(&)[4]) (nor substring::substring(const char*)).

How overload operator < for sort method for objects?

I have this object, for example
class Employee{
int id;
string name;
string secName;
}
My main is :
int main(){
vector<Employee> vec = {Employee(1, "Andy", "Good"), Employee(5, "Adam", "Bad"), Employee(2, "Some", "Employee")}
sort(vec.begin(), vec.end())
}
I know how overload sort method for vector when I have one parameter for sorting. It's like:
bool operator<(Employee a, Employee b ){
if (a.name<b.name) return true;
else return false;
}
But the point is that I have sort not only on one parameter, but on all. So how should I change overloading method?
I've tried this way, but it doesn't work.
bool operator<(Employee a, Employee b)
{
if (a.id < b.id)
if (a.name < b.name)
if (a.surname<b.surname)return true; else return false;
else return false;
else return false;
}
If you want to sort primarily by id, secondarily by name and tertiary by secName this should work:
bool operator<(Employee a, Employee b)
{
if (a.id < b.id) return true;
if (a.id > b.id) return false;
if (a.name < b.name) return true;
if (a.name > b.name) return false;
if (a.secName < b.secName) return true;
return false;
}
If you want to sort primarily by id, secondarily by name and tertiarily by secName, you could use this trick involving std::tie:
#include <tuple>
// ...
bool operator<(const Employee& lhs, const Employee& rhs)
{
return std::tie(lhs.id, lhs.name, lhs.secName)
< std::tie(rhs.id, rhs.name, rhs.secName);
}
It's also best for the function parameters to be passed in as const-refs (const &).

C++ Calling a Double dispatch method with objects that are not relative to each other

I have a series of shape objects that can check if they intersect one another (an intersection is true if any part of either object overlaps the other). This works great with double dispatch because the intersection of two objects can be represented relative to either object and still be valid and true.
I recently added (read as: "attempted to add") a Contains method that tests whether or not a shape completely encloses another. The double dispatch fails because two shapes of differing sizes will work for Intersect but not Contains: shape_one is a big circle, and shape_two is a smaller circle completely enclosed by shape_one. The call shape_one.Contains(shape_two) will return true but shape_two.Contains(shape_one) will return false.
Is there a way to implement double dispatch for this type of scenario?
(Title edits are encouraged to increase comprehension of question...)
A sample of the Intersects methods with double dispatch:
bool Rectangle::Intersects(const Shape& shape) const {
return shape.Intersects(*this);
}
bool Rectangle::Intersects(const Point& point) const {
return point.Intersects(*this);
}
bool Rectangle::Intersects(const Line& line) const {
return line.Intersects(*this);
}
bool Rectangle::Intersects(const Rectangle& rectangle) const {
double myTop = this->GetY();
double myLeft = this->GetX();
double myRight = myLeft + this->GetWidth();
double myBottom = myTop + this->GetHeight();
double rTop = rectangle.GetY();
double rLeft = rectangle.GetX();
double rRight = rLeft + rectangle.GetWidth();
double rBottom = rTop + rectangle.GetHeight();
if(myTop > rBottom) return false;
if(myBottom < rTop) return false;
if(myLeft > rRight) return false;
if(myRight < rLeft) return false;
return true;
}
A sample of the Contains methods with double dispatch:
//THIS RESULTS IN A STACK OVERFLOW! DUE TO INFINITE RECURSION!
bool Rectangle::Contains(const Shape& shape) const {
return this->Contains(shape);
}
//THIS IS NOT TRUE IN ALL CASES!
bool Rectangle::Contains(const Shape& shape) const {
return shape.Contains(*this);
}
bool Rectangle::Contains(const Point& point) const {
return this->Intersects(point);
}
bool Rectangle::Contains(const Line& line) const {
return this->Intersects(line.GetPointOne()) && this->Intersects(line.GetPointTwo());
}
bool Rectangle::Contains(const Rectangle& rectangle) const {
return this->Intersects(rectangle.GetTopLeft()) && this->Intersects(rectangle.GetTopRight()) && this->Intersects(rectangle.GetBottomLeft()) && this->Intersects(rectangle.GetBottomRight());
}
Solved via pushing contains methods up to base class and a dynamic cast to the proper type with a type parameter in the base-to-base Contains call:
bool Shape::Contains(const Shape& shape) const {
std::string type = shape.GetShapeType();
if(type == "arc") {
return this->Contains(dynamic_cast<const Arc&>(shape));
} else if(type == "circle") {
return this->Contains(dynamic_cast<const Circle&>(shape));
} else if(type == "ellipse") {
return this->Contains(dynamic_cast<const Ellipse&>(shape));
} else if(type == "line") {
return this->Contains(dynamic_cast<const Line&>(shape));
} else if(type == "point") {
return this->Contains(dynamic_cast<const Point&>(shape));
} else if(type == "polygon") {
return this->Contains(dynamic_cast<const Polygon&>(shape));
} else if(type == "rectangle") {
return this->Contains(dynamic_cast<const Rectangle&>(shape));
} else if(type == "sector") {
return this->Contains(dynamic_cast<const Sector&>(shape));
} else if(type == "spline") {
return this->Contains(dynamic_cast<const Spline&>(shape));
} else if(type == "triangle") {
return this->Contains(dynamic_cast<const Triangle&>(shape));
} else {
return false;
}
}
bool Shape::Contains(const Point& point) const {
return this->Intersects(point);
}
bool Shape::Contains(const Line& line) const {
return this->Intersects(line.GetPointOne()) && this->Intersects(line.GetPointTwo());
}
bool Shape::Contains(const Rectangle& rectangle) const {
return this->Intersects(rectangle.GetTopLeft()) && this->Intersects(rectangle.GetTopRight()) && this->Intersects(rectangle.GetBottomLeft()) && this->Intersects(rectangle.GetBottomRight());
}
//...etc