I am having a problem with pieces[] at Copy Constructor and Equal Oparator. i am trying to get pieces like code and month_year but it drops me an error saying 'class machine' has no member named 'get'
#include <iostream>
#include <string>
using namespace std;
class machine {
public:
void set_code(string my_code){
code=my_code;
}
void set_month_year(int my_month_year){
month_year=my_month_year;
}
void set_pieces(int *my_pieces){
for(int i=0;i<25;i++)
pieces[i]=my_pieces[i];
}
string get_code(void){
return code;
}
int get_month_year(void){
return month_year;
int get_pieces_i(int i){
return pieces[i];
}
//Default Constructor
machine(){
code.erase();
month_year=0;
for(int i=0;i<25;i++)
pieces[i]=0;
}
//Destructor
~machine(){}
void print_data(void){
cout << "Code= " << code << endl;
cout << "Month Year " << month_year << endl;
}
void print_pieces(void){
for(int i=0;i<25;i++)
cout << pieces[i] << endl;
}
machine(string my_code, int my_month_year,int *my_pieces){
code=my_code;
month_year=my_month_year;
for(int i=0;i<25;i++)
pieces[i]=my_pieces[i];
}
//Copy Constructor
machine (machine& a)
{
code=a.get_code();
month_year=a.get_month_year();
pieces=a.get.pieces_i();
}
//Equal Operator
void operator = (machine & a)
{
code=a.get_code();
month_year=a.get_month_year();
pieces=a.get_pieces_i();
}
// month & year
int get_month(void) {
return month_year/100;
}
int get_year(void) {
return month_year%100;
}
//return 0 & 1
int ckeck_code(void) {
int counter=0;
for (int i=0;i<25;i++) {
if (pieces [i] <10) {
counter=counter+1;
}
if (counter<5)
return 0;
else
return 1;
}
}
private:
string code;
int month_year;
int pieces[25];
};
int main(void){
return 0;
}
Both copy constructor and assignment operator (yes, it's called assignment operator, not equal operator) should have their parameter of type const machine& instead of machine&.
On the get_* functions, they should be declared as constant member functions. That is,
string get_code(void) const {
return code;
}
int get_month_year(void) const {
return month_year;
}
int get_pieces_i(int i) const {
return pieces[i];
}
Furthermore, the copy constructor and assignment operator should handle pieces like:
for (int i = 0; i < 25; ++i)
pieces[i] = a.get_pieces_i(i);
to match the getters' prototype.
Related
I am defining my own string class called StringSet using a vector of strings. I am assigned to overload the >>, <<, ==, >, >=, +, += and * operators, and ran into a problem with <<. The output should be:
Welcome to stringset
hi everyone
"all" does not exist in the set.
hi
But it seems to be skipping the second and third lines. I am very new to overloading operators, so I am probably overlooking an obvious mistake.
header and class declaration:
#include <iostream>
#include <vector>
#include<string>
#include <iterator>
#include <algorithm>
#include <fstream>
using namespace std;
class StringSet
{
public:
//Constructor
StringSet();
//Copy Constructor
StringSet(const StringSet& s);
//Default constructors
StringSet(string initialStrings[], const int ARRAYSIZE);
//Destructor
~StringSet();
void add(const string s);
void remove(const string s);
//Returns length
int size()
{
return length;
}
// Overload the << operator so that it outputs the strings
friend ostream& operator <<(ostream& outs, const StringSet& s);
private:
//size of the vector
int length;
// Vector to store strings
vector <string> data;
};
function definitions:
ostream& operator<<(ostream& outs, const StringSet& s)
{
outs << "\n";
for (int i = 0; i < s.length; i++)
{
outs << s.data[i] << " ";
}
outs << "\n";
return outs;
}
//Add a string to the vector
void StringSet::add(const string s)
{
bool c = check(s);
if (c == false)
{
data.push_back(s);
}
else
{
cout << "\"" << s << "\" already exists in the set.";
}
}
// Remove a string from the vector
void StringSet::remove(const string s)
{
bool c = check(s);
if (c == true)
{
vector<string>::iterator position = search(s);
data.erase(position);
}
else
{
cout << "\"" << s << "\" does not exist in the set\n";
}
}
StringSet::StringSet()
{
length = 0;
}
StringSet::StringSet(string initialStrings[], const int ARRAYSIZE)
{
for (int i = 0; i < data.size(); i++)
{
initialStrings[i] = " ";
}
}
// Copy constructor
StringSet::StringSet(const StringSet& s)
{
for (int i = 0; i < data.size(); i++)
{
data[i] = s.data[i];
}
}
StringSet::StringSet()
{
length = 0;
}
StringSet::StringSet(string initialStrings[], const int ARRAYSIZE)
{
for (int i = 0; i < data.size(); i++)
{
initialStrings[i] = " ";
}
}
// Copy constructor
StringSet::StringSet(const StringSet& s)
{
for (int i = 0; i < data.size(); i++)
{
data[i] = s.data[i];
}
}
// Check if a string exists in the vector
bool StringSet::check(const string s)
{
vector<string>::iterator it = find(data.begin(), data.end(), s);
if (it != data.end())
{
return true;
}
else
{
return false;
}
}
Main function:
int main()
{
ofstream outs;
ifstream ins;
StringSet doc1, doc2, query
cout << "Welcome to stringset\n";
doc1.add("hi");
doc1.add("everyone");
outs << doc1;
doc1.remove("everyone");
doc1.remove("all");
outs << doc1;
}
If you use a variable that stores the size of the set, you should increment/decrement it when adding/removing elements. You can also change the definition of the StringSet::size():
int size() const
{
return static_cast<int>(data.size());
}
I have written a program which was given to me as a homework assignment (it's a bit longer). The issue is that it compiles in CodeBlocks but it does not compile in Visual Studio 2017 it says - binary '=': no operator found which takes a right-hand operand of type 'CAutomobile' (or there is no acceptable conversion.
I would like to ask why is that because I could not myself find the error? I tried commenting the operator =function but still the error remained.
#include <iostream>
#include <algorithm>
#include <string>
#include <stdlib.h>
using namespace std;
class CVehicle {
string name;
int year;
public:
CVehicle() {
name = "Car";
year = 1990;
}
CVehicle(string n, int y) {
name = n;
year = y;
}
CVehicle(const CVehicle& vc) {
name = vc.name;
year = vc.year;
}
void setName(string n) {
name = n;
}
void setYear(int y) {
year = y;
}
string getName() {
return name;
}
int& getYear() {
return year;
}
virtual void Print(ostream& os) = 0;
};
class CAutomobile :public CVehicle {
double litres;
public:
CAutomobile() :CVehicle() {
litres = 7.2;
}
CAutomobile(string nm, int yr, double l) :CVehicle(nm, yr) {
litres = l;
}
void setLitres(double l) {
l = litres;
}
double& getLitres() {
return litres;
}
void Print(ostream& os) override {
os << getName() << endl;
os << getYear() << endl;
os << litres << endl;
}
friend bool operator< (CAutomobile a1, CAutomobile a2) {
if (a1.litres < a2.litres) {
return true;
}
return false;
}
CAutomobile operator= (CAutomobile& at) {
CAutomobile au;
au.getName() = at.getName();
au.getYear() = at.getYear();
au.getLitres() = at.getLitres();
return au;
}
CAutomobile operator+(CAutomobile aut) {
CAutomobile a;
a.getLitres() = getLitres() + aut.getLitres();
return a;
}
friend ostream& operator<< (ostream& o, CAutomobile a) {
o << a.getName() << endl;
o << a.getYear() << endl;
o << a.getLitres() << endl;
return o;
}
};
int main()
{
CAutomobile a[] = {
CAutomobile(),
CAutomobile("Wolkswagen",1970,80.5),
CAutomobile("Fiat",1979,21.9),
CAutomobile("Opel",1978,13.7)
};
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) {
cout << "Name" << ' ' << a[i].getName() << endl;
cout << "Year" << ' ' << a[i].getYear() << endl;
cout << "Litres" << ' ' << a[i].getLitres() << endl;
}
int range = 2016 - 1990 + 1;
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) {
a[i].setLitres(rand() % 100 + 1);
a[i].setYear(rand() % range + 1996);
}
//сортираме масива по литри и извеждаме
//най малкия (първия) му елемент
for (int i = 0; i < sizeof(a-1); i++) {
for (int j = 0; j < sizeof(a-1); j++) {
if (a[j].getLitres() > a[j + 1].getLitres()) {
swap(a[j], a[j + 1]);
}
}
}
cout << a[0] << endl;
CAutomobile k = a[0] + a[3];
cout << k.getLitres() << endl;
}
CAutomobile::operator = is completely wrong. It takes a non-const reference and assignes its field to a new object. Instead it should take a const reference and modify current object.
CAutomobile & operator =(CAutomobile const & other)
{
assert(this != ::std::addressof(other)); // check for self-assignment
SetName(other.getName());
SetYear(other.getYear());
SetLitres(other.getLitres());
return *this;
}
This will bring up another problem: getters are not const-qualified, so they should be fixes as well:
string const & getName(void) const {
return name;
}
int const & getYear(void) const {
return year;
}
I'm quite new to c++ and netbeans and have quite a problem here and I can't put my finger on what the error might be.
Building is always succesful but I get a RUN FAILED (exit value -1.073.740.940, total time: 2s) error, when running my program. My code:
Arraylist.hpp:
#include <iostream>
namespace hfu {
class Arraylist {
private:
double* members;
int size;
public:
Arraylist(int);
~Arraylist();
Arraylist(const Arraylist&);
double get(int) const;
void set(int, double);
Arraylist& operator=(const Arraylist&);
//float operator[](int);
friend std::ostream& operator<<(std::ostream&, const Arraylist&);
};
}
Arraylist.cpp:
#include "Arraylist.hpp"
#include <exception>
namespace hfu {
Arraylist::Arraylist(int i) : size(i), members(new double[size]) {
for (int i = 0; i < size; i++) {
set(i, 0);
}
}
Arraylist::~Arraylist() {
delete members;
}
Arraylist::Arraylist(const Arraylist& other) : size(other.size), members(new double[other.size]) {
for (int i = 0; i < 5; i++) {
set(i, other.get(i));
}
}
double Arraylist::get(int i) const {
if (i < 0 || i >= size) {
throw (std::exception());
} else {
return members[i];
}
}
void Arraylist::set(int i, double value) {
if (i < 0 || i >= size) {
throw (std::exception());
} else {
members[i] = value;
}
}
Arraylist& Arraylist::operator=(const Arraylist& other) {
size = other.size;
for (int i = 0; i < size; i++) {
set(i, other.get(i));
}
return *this;
}
// float Arraylist::operator [](int index) {
// return members[index];
// }
std::ostream& operator<<(std::ostream& os, const Arraylist& list) {
for (int i = 0; i < list.size; i++) {
os << "[" << list.get(i) << "]";
}
return os;
}
}
main.cpp:
#include "Arraylist.hpp"
int main() {
try {
auto a1 = hfu::Arraylist(10);
std::cout << a1 << std::endl;
auto a2 = hfu::Arraylist(10);
std::cout << a2 << std::endl;
auto a3 = hfu::Arraylist(10);
std::cout << a3 << std::endl;
}
catch (std::exception& e) {
std::cout << e.what() << std::endl;
}
}
I can create 2 objects of Arraylist.... but not more, it will print the first two and then fail.... but when I create shorter lists, say 3 with only size one... it will work... so I think it might be something with the memory... but I'm at a loss. Ideas?
Thanks a lot!
btw: I'm using netbeans 8.2 and mingw g++ 6.1.0
The initialization order of the member variables is defined by the order of their definitions in the class, not by their order in the initializer list. As a matter of fact, your compiler should be giving you "hfu::Arraylist::size will be initialized after" warnings.
So in your case, members gets initialized before size, thus new double[size] is called when size is still garbage. In my case it simply causes std::bad_array_new_length to be thrown. In your case, things go worse and your application crashes.
So the solution is to change
class Arraylist {
private:
double* members;
int size;
to
class Arraylist {
private:
int size;
double* members;
I'm trying to implement a Matrix template. I've overloaded the <<, >> and + operators. << and >> are working properly but + is not working as expected. After using the + operator I am getting some random output in the last line. Can anyone tell me what is wrong?
#include<iostream>
using namespace std;
template <class V>
class mat
{
public:
int row,col;
V **a;
mat(int r,int c)
{
row=r;
col=c;
a=new V*[r];
for(int i=0;i<row;i++)
{
a[i]=new V[col];
}
}
mat(const mat &x) //Copy constructor
{
row=x.row;
col=x.col;
a=new V*[row];
for(int i=0;i<row;i++)
{
a[i]=new V[col];
}
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
a[i][j]=x.a[i][j];
}
}
}
~mat()
{
//cout << "Deleting Matrix\n" << endl;
for(int i=0;i<row;i++)
{
delete []a[i];
}
}
friend ostream &operator<<(ostream &p,const mat &z)
{
for(int i=0;i<z.row;i++)
{
for(int j=0;j<z.col;j++)
{
p << z.a[i][j] <<" ";
}
cout << endl;
}
return p;
}
friend istream &operator>>(istream &p,mat &z)
{
for(int i=0;i<z.row;i++)
{
for(int j=0;j<z.col;j++)
{
p >> z.a[i][j];
}
}
return p;
}
mat<V> operator+(mat<V> z)
{
mat<V> b(row,col);
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
b.a[i][j]=a[i][j]+z.a[i][j];
}
}
return b;
}
};
int main()
{
mat<int> p(2,2),q(2,2),z(2,2);
cin>>p>>q;
cout<<p<<q<<endl; //working properly
z=p+q;
cout<<z<<endl; // getting wrong output here
return 0;
}
In C++, I recommand to use operator +=, -=, *=, /= and others like them be internal to the class. The operators +, *, -, / should be external.
So you could do something like this:
class A {
A &operator +=(A const &b) {
... code
return *this;
}
};
A operator+(A a1, A const &a2) {
return a1 += a2;
}
thanks to vsoftco for the tip
To answer more precisely to your question, you just did not define the operator=
If you do mat z = p + q; it will works ;).
See my comments below for further details ;)
Inside of your operator+ you effectively have b = (*this) + z. You only however, check row and col from this. If z is smaller in either dimension you are going to be out of bounds.
You can check for this condition and figure out what to return if that happens (or throw an exception, the choice is yours):
mat<V> operator+(const mat<V>& z) const {
mat<V> b(row,col);
if (z.row != row || z.col != col) { return b; }
// ...
}
Or you can have the mat class be templated on the dimensions as well, which would make two different size matrices be different types
template <typename T, int Row, int Col>
class mat {
private:
T a[Row][Col];
// ...
};
The internals of your functions are working fine. But as others have mentioned above, there is something wrong with your function signatures, that is causing them to be called in a rather strange way.
I have added some debug output to your code to illustrate what is happening. You should add these changes, compile and run.
#include<iostream>
using namespace std;
template <class V>
class mat
{
public:
int row,col;
V **a;
mat(int r,int c)
{
row=r;
col=c;
a=new V*[r];
for(int i=0;i<row;i++)
{
a[i]=new V[col];
for (int cc=0; cc<col;++cc)
{
a[i][cc] = -77;
}
}
}
mat(const mat &x) //Copy constructor
{
cout << "copy to this: " << this << endl;
cout << "x: " << &x << endl;
row=x.row;
col=x.col;
a=new V*[row];
for(int i=0;i<row;i++)
{
a[i]=new V[col];
}
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
a[i][j]=x.a[i][j];
}
}
}
~mat()
{
//cout << "Deleting Matrix\n" << endl;
for(int i=0;i<row;i++)
{
delete []a[i];
}
}
friend ostream &operator<<(ostream &p,const mat &z)
{
for(int i=0;i<z.row;i++)
{
for(int j=0;j<z.col;j++)
{
p << z.a[i][j] <<" ";
}
cout << endl;
}
return p;
}
friend istream &operator>>(istream &p,mat &z)
{
for(int i=0;i<z.row;i++)
{
for(int j=0;j<z.col;j++)
{
p >> z.a[i][j];
}
}
return p;
}
mat<V> operator+(mat<V> z)
{
cout << "plus to this: " << this << endl;
mat<V> b(row,col);
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
b.a[i][j]=a[i][j]+z.a[i][j];
}
}
return b;
}
};
int main()
{
mat<int> p(2,2),q(2,2),z(2,2);
cin>>p>>q;
cout<<p<<q<<endl; //working properly
cout << "Before" << endl;
cout << "p : " << &p << endl;
cout << "q : " << &q << endl;
cout << "z : " << &z << endl;
cout << "After" << endl;
z=p+q;
cout<<q<<endl;
cout<<z<<endl; // getting wrong output here
return 0;
}
When I run I see the following output.
Before
p : 0026F75C
q : 0026F748
z : 0026F734
After
copy to this: 0026F61C
x: 0026F748
plus to this: 0026F75C
copy to this: 0026F654
x: 0026F5E8
From this you can see that when the line
z=p+q;
is run, the copy constructor is called to copy q to an anonymous object, then the operator+ function is called on another anonymous object.
Finally, when exiting the operator+ function, the copy constructor is called again, copying the result of operator+ function to a third anonymous object. At no time is anything copied to z, nor is the operator+ function called on p or q.
This code also segfaults on exit. I think the problem lies with creating anonymous objects, which is using the default constructor created by the compiler, which does not set row, col or intialise a.
After really hard search for answers...
I tried fo(u)r hours to get and set values to an array with Overloading the subscript operator “[ ]” but can't figure out why it won't work.
What I'm tring to do here is to set someType value to an array member (On Main "darr1[i] = i*10.0" for example) with overloading the [] and with overloading the = and to get someType value from an array member (On Main "<< darr1[i] << endl" for example) but can't figure out why just the overloading of: "Type & operator [] (int index)" is invoking.
My program doesn't get to the '=' overloading or to the second '[]' overloading at all..
here is my program (sorry for the long one):
#include <iostream>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
class AO1Array
{
private:
int _size;
protected:
int top;
int *B;
int *C;
AO1Array(int n);
~AO1Array();
bool isRealValue(int index)
{
if ((0 <= B[index] && B[index] < top) && (index == C[B[index]]))
return true;
return false;
};
};
AO1Array::AO1Array(int n)
{
_size = n;
top = 0;
B = new int[n];
C = new int[n];
}
AO1Array::~AO1Array()
{
delete[] B;
B = NULL;
delete[] C;
C = NULL;
}
template<class Type>
class GenericO1Array : AO1Array
{
public:
GenericO1Array(int size, Type initVal) : AO1Array(size)
{
_initVal = initVal;
Len = size;
A = new Type[size];
}
~GenericO1Array()
{
delete[] A;
A = NULL;
}
int Length() { return Len; }
Type & operator [](int index) const
{
if (AO1Array::isRealValue(index))
return A[index];
return _initVal;
}
Type & operator [] (int index)
{
if (AO1Array::isRealValue(index))
realValue = true;
else
realValue = false;
return A[index];
}
Type operator =(Type value)
{
if (realValue)
A[lastIndex] = _initVal;
else
{
AO1Array::C[top] = lastIndex;
AO1Array::B[lastIndex] = AO1Array::top++;
A[index] = value;
}
return *this;
}
private:
int Len;
int lastIndex;
bool realValue;
Type _initVal;
Type *A;
};
int main()
{
int n = 20;
GenericO1Array<double> darr1(n, 1.1);
GenericO1Array<long> iarr1(n, 2);
int i;
cout << "\nLength.darr1 = " << darr1.Length() << endl;
cout << "\nLength.iarr1 = " << iarr1.Length() << endl;
for (i = 0; i < n; i += 2)
{
darr1[i] = i*10.0;
iarr1[i] = i * 100;
} // for
cout << "\ndarr1 = " << endl;
for (i = 0; i < n; i++)
cout << "darr1[" << i << "] = " << darr1[i] << endl;
cout << "\niarr1 = " << endl;
for (i = 0; i < n; i++)
cout << "iarr1[" << i << "] = " << iarr1[i] << endl;
} // main
My program doesn't get to the '=' overloading
You are overloading the = assignment operator of Generic01Array itself, but nothing in your code is actually assigning values to your darr1 or iarr1 variables directly (there are no darr1 = ... or iarr = ... statements). That is why your = operator is not being invoked.
If you want something to happen when the user assigns a value to an element of your array, you need to create a proxy class and overload its = assignment operator, then have your [] operator return an instance of that proxy:
template<class Type>
class GenericO1Array : AO1Array
{
public:
class Proxy;
friend Proxy;
class Proxy
{
private:
Generic01Array& _arr;
int _index;
public:
Proxy(Generic01Array &arr, int index) : _arr(arr), _index(index) {}
operator Type() const
{
if (_arr.isRealValue(index))
_arr.realValue = true;
else
_arr.realValue = false;
return _arr.A[_index];
}
Proxy& operator=(const Type &value)
{
if (_arr.realValue)
_arr.A[_arr.lastindex] = _arr._initVal;
else
{
_arr.C[_arr.top] = _arr.lastIndex;
_arr.B[_arr.lastIndex] = _arr.top++;
_arr.A[_index] = value;
}
return *this;
}
};
...
Proxy operator [] (int index)
{
return Proxy(*this, index);
}
...
};
or to the second '[]' overloading at all..
You have two overloads of the [] operator, one that is const and the other is not. The const version of [] is breaking the const-ness of the operator by returning a non-const reference to the array's internal data. It should be returning a non-reference const value instead:
const Type operator [](int index) const
The non-const version of the [] operator can return a reference:
Type& operator [](int index)
You are not calling the [] operator on any const instances of your Generic01Array class, so only the non-const version of your [] operator should be getting invoked.