How do I create a copy constructor that copies an object to the newly instantiated object?
Also, how do I use the == operator to compare the speed of two Tricycle
objects?
Here is the sample code:
#include <iostream>
class Tricycle
{
private:
int* speed;
//static int speedlim;
public:
Tricycle();
// copy constructor and destructor use default
int getSpeed() const { return *speed; }
//static int getspeedlim() {return speedlim;}
void setSpeed(int newSpeed) { *speed = newSpeed; }
Tricycle operator=(const Tricycle&);
void operator++();
void operator++(int);
};
//Tricycle operator++();
//Tricycle operator++(Tricycle,int);
Tricycle::Tricycle()
{
speed = new int;
*speed = 5;
//speedlim=40;
}
Tricycle Tricycle::operator=(const Tricycle& rhs){
if (this == &rhs)
return *this;
delete speed;
//speed = new int;
//*speed = rhs.getSpeed();
return *this;
}
void Tricycle::operator++(){
(*speed)++;}
void Tricycle::operator++(int){
(*speed)++;}
int main()
{
Tricycle wichita;
//std::cout << "the speed limit is : " << Tricycle::getspeedlim();;
std::cout << "Wichita's speed : " << wichita.getSpeed() << "\n";
std::cout << "Setting Wichita's speed to 6 ...\n";
wichita.setSpeed(6);
Tricycle dallas;
std::cout << "Dallas' speed : " << dallas.getSpeed() << "\n";
std::cout << "Copying Wichita to Dallas ...\n";
wichita = dallas;
std::cout << "Dallas' speed : " << dallas.getSpeed() << "\n";
wichita.setSpeed(5);
wichita++;
std::cout << "Wichita's speed : " << wichita.getSpeed() << "\n";
wichita.setSpeed(5);
++wichita;
std::cout << "Wichita's speed : " << wichita.getSpeed() << "\n";
return 0;
}
Here is a test I tried using pre-increment and post-increment to increment the speed. This is the answer:
Wichita's speed : 5
Setting Wichita's speed to 6 ...
Dallas' speed : 5
Copying Wichita to Dallas ...
Dallas' speed : 5
Wichita's speed : 6
Wichita's speed : 6
How do I create a copy constructor that copies an object to the newly instantiated object?
Like this:
class Tricycle
{
...
public:
...
Tricycle(const Tricycle&);
...
};
Tricycle::Tricycle(const Tricycle &src)
{
speed = new int;
*speed = src.getSpeed(); // or: *(src.speed)
// or:
// speed = new int(src.getSpeed()); // or: *(src.speed)
}
Also, how do I use the == operator to compare the speed of two Tricycle objects?
Like this:
class Tricycle
{
...
public:
...
bool operator==(const Tricycle&) const;
...
};
bool Tricycle::operator==(const Tricycle &rhs) const
{
return getSpeed() == rhs.getSpeed();
// or:
// return *speed == *(rhs.speed);
}
That said, there are some other problems with your code:
Tricycle is missing a destructor to free the allocated speed, thus leaking it. The default compiler-generated destructor is not sufficient, just like the copy constructor and assignment operator.
the assignment operator= and pre-increment operator++ need to return a Tricycle& reference to *this, and the post-increment operator++ needs to return a Tricycle copy of *this before speed was updated. See What are the basic rules and idioms for operator overloading?
the assignment operator= is leaving speed in an invalid state. It is freeing speed but not reallocating it or setting it to NULL. There is no reason for it to free speed at all, just set its value.
Try this:
class Tricycle
{
private:
int* speed;
//static int speedlim;
public:
Tricycle();
Tricycle(const Tricycle&);
~Tricycle();
int getSpeed() const { return *speed; }
//static int getspeedlim() { return speedlim; }
void setSpeed(int newSpeed) { *speed = newSpeed; }
Tricycle& operator=(const Tricycle&);
Tricycle& operator++();
Tricycle operator++(int);
};
//int Tricycle::speedlim = 40;
Tricycle::Tricycle()
{
speed = new int(5);
}
Tricycle::Tricycle(const Tricycle &src)
{
speed = new int(*(src.speed));
}
Tricycle::~Tricycle()
{
delete speed;
}
Tricycle& Tricycle::operator=(const Tricycle& rhs)
{
if (this != &rhs)
*speed = rhs.getSpeed();
return *this;
}
Tricycle& Tricycle::operator++()
{
++(*speed);
return *this;
}
Tricycle Tricycle::operator++(int)
{
Tricycle temp(*this);
++(*speed);
return temp;
}
That said, there is no good reason for speed to be dynamically allocated at all. If you get rid of that allocation, then the default compiler-generated destructor, copy constructor, and copy assignment operator will be sufficient, so you don't need to define them at all:
class Tricycle
{
private:
int speed;
//static int speedlim;
public:
Tricycle();
int getSpeed() const { return speed; }
//static int getspeedlim() { return speedlim; }
void setSpeed(int newSpeed) { speed = newSpeed; }
Tricycle& operator++();
Tricycle operator++(int);
};
//int Tricycle::speedlim = 40;
Tricycle::Tricycle()
{
speed = 5;
}
Tricycle& Tricycle::operator++()
{
++speed;
return *this;
}
Tricycle Tricycle::operator++(int)
{
Tricycle temp(*this);
++speed;
return temp;
}
Related
This question already has answers here:
What is The Rule of Three?
(8 answers)
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 7 months ago.
Please explain to me why the destructor gets called on the "strand" object after its assigned with "tari" members. this question has been puzzling me and I haven't been able to move on from it as it gives me the wrong answer of 5 at the end instead of 10 when i try to add the contents of the "jesu" objects because the destructor gets called and any operation done on strand object becomes obsolete
#include <iostream>
#include <iomanip>
using namespace std;
class Bheki
{
private:
string name;
int sam;
double *jesu = nullptr;
public:
Bheki(){}
void Hvo()
{
jesu = new double(5);
}
double* getJesu() const
{
return jesu;
}
void setName(string Gama){name = Gama;}
void setSam(int ram){sam=ram;}
string getName()const{
return name;
}
int getSam()const{
return sam;
}
~Bheki(){
delete jesu;
jesu = nullptr;
}
const Bheki operator=(const Bheki &);
const Bheki operator+(const Bheki &);
};
const Bheki Bheki::operator+(const Bheki &ned)
{
Bheki temp;
temp.sam = sam + ned.sam;
temp.jesu = new double();
*temp.jesu = (*jesu) + (*ned.jesu);
cout<<*temp.jesu<<endl;
return temp;
}
const Bheki Bheki::operator =(const Bheki &pop)
{
if(this != &pop)
{
this->name = pop.name;
this->sam =pop.sam;
this->jesu = new double{};
*this->jesu = *pop.jesu;
}
return *this;
}
int main()
{
Bheki *tari = new Bheki();
tari->Hvo();
tari->setName("jece");
tari->setSam(6969);
cout<<tari->getName()<<endl;
Bheki *strand = new Bheki;
*strand = *tari;
cout<<strand->getName()<<endl;
strand->setName("Kumkani");
cout<<tari->getName()<<endl;
*strand->getJesu()=20.325;
cout<<strand->getJesu()<<endl;
cout<<tari->getJesu()<<endl;
*strand->getJesu() = 32;
cout<<*tari->getJesu()<<endl;
strand->setSam(884);
tari-> setSam(7);
cout<<*tari->getJesu()<<endl;
*strand->getJesu() = 5;
*tari->getJesu() = 5;
Bheki *balo = new Bheki;
*balo = *strand + *tari;
cout<<*balo->getJesu()<<endl;
cout<<balo->getSam()<<endl;
// delete tari;
// delete balo;
// delete strand;
return 0;
}
I compare my code with another post I found posted by #Serge Rogatch who said that it does not get called at assignment but mine does get called which completely contradicts each other
#include <iostream>
#include <string>
class Test
{
std::string _name;
public:
Test(std::string name ="") : _name(name) { }
~Test()
{
std::cout << "Destructor " << _name << std::endl;
}
Test& operator=(const Test& fellow)
{
// avoid changing the name of the object
std::cout << "Assignment operator "
<< _name << "=" << fellow._name << std::endl;
return *this;
}
};
int main()
{
Test t1, t2("t2");
t1 = t2;
return 0;
}
#include <iostream>
class Piece {
public:
virtual char get()=0;
virtual ~Piece() {};
};
class One : public Piece {
public:
char get() { return '1'; }
};
class Two : public Piece {
public:
char get() { return '2'; }
};
class Tile {
private:
Piece* occ;
bool prs;
public:
Tile() { prs = false; }
void setOcc(Piece* p) { prs = true; occ = p; }
Piece& getOcc() { return *occ; }
bool getPrs() { return prs; }
void explicitDest() { if (prs) { delete occ; prs = false; } }
};
class Board {
private:
Tile tiles[2][2];
public:
Board() {
tiles[0][0].setOcc(new One());
tiles[0][1].setOcc(new Two());
tiles[1][1].setOcc(new One());
}
Tile getTile(int c, int r) { return tiles[c][r]; }
void move(Board* b, int c1, int r1, int c2, int r2) {
switch(b->tiles[c1][r1].getOcc().get()) {
case '1': b->tiles[c2][r2].setOcc(new One()); break;
case '2': b->tiles[c2][r2].setOcc(new Two()); break;
}
b->tiles[c1][r1].explicitDest();
}
void print() {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
if (tiles[j][i].getPrs()) {
std::cout << tiles[j][i].getOcc().get() << " ";
} else {
std::cout << "- ";
}
}
std::cout << "\n";
}
std::cout << "\n";
}
Board* copyBoard() { return new Board(*this); }
};
int main()
{
Board* oldBoard = new Board();
std::cout << "Old board: \n";
oldBoard->print();
Board* newBoard = oldBoard->copyBoard();
std::cout << "New board: \n";
newBoard->print();
newBoard->move(newBoard, 0, 0, 1, 1);
std::cout << "Old board after move: \n";
oldBoard->print();
std::cout << "New board after move: \n";
newBoard->print();
delete[] newBoard;
}
This is an MRE to illustrate the methodology I've been using to do deep copies. It doesn't exactly work and is just to visualize how I've been doing things.
Using this example, is my method for deep copying strong? If not, what methods are available with a C++03 constraint to ensure a copy (and changes to the copy) do not reflect upon the original it's based upon?
In the code, I defined explicitDest() which is my way of explicitly (and only explicitly) calling the destructor as I need certain behavior only sometimes. Just in case people asked.
I'm not terribly familiar with copying, copy constructors, or abstract classes/methods if the code wasn't obvious.
You should implement copy constructors and copy assignment operators and take care when using new. You need one delete for each new - unless you surrender the pointer returned by new to a smart pointer. In C++03 you have std::auto_ptr that can be used to manage the memory resources for you.
Here's an example with comments inline:
#include <iostream>
#include <memory> // std::auto_ptr
#include <algorithm> // std::swap (<algorithm> in c++03, <utility> in >= c++11)
class Piece {
public:
// A virtual destructor to support deleting via base class pointer:
virtual ~Piece() {}
// You can't make constructors virtual, so add a clone()
// function for copy constuction through a base class pointer
virtual std::auto_ptr<Piece> clone() const = 0;
// renamed get() into symbol()
virtual char symbol() const = 0;
};
class One : public Piece {
public:
// Use the implicit copy constructor for One and return a (smart) pointer
// to the base class.
std::auto_ptr<Piece> clone() const {
return std::auto_ptr<Piece>(new One(*this));
}
char symbol() const { return '1'; }
};
class Two : public Piece {
public:
std::auto_ptr<Piece> clone() const {
return std::auto_ptr<Piece>(new Two(*this));
}
char symbol() const { return '2'; }
};
class Tile {
private:
std::auto_ptr<Piece> occ; // this now handles delete for you
public:
Tile() : occ(NULL) {} // default constructor
Tile(Piece* p) : occ(p) {} // put pointer in auto_ptr
// copy constructor, use the clone() function and conversion
// to bool operator below. If "o" doesn't have a Piece, initialize occ
// with an default constructed, empty, auto_ptr<Piece>.
Tile(const Tile& o) : occ(o ? o.occ->clone() : std::auto_ptr<Piece>()) {}
// ^
// |
// +--- conversion to bool in use
// copy assignment operator
Tile& operator=(const Tile& o) {
Tile tmp(o); // use the copy constructor above
occ = tmp.occ; // steal pointer from tmp
return *this;
}
// converting assignment operator
Tile& operator=(Piece* p) {
// delete the old pointer and replace it with p:
occ.reset(p);
return *this;
}
// Conversion to bool operator using std::auto_ptr's built in get()
// to tell us if we have a Piece or not.
operator bool() const { return occ.get() != NULL; }
// Add a symbol() function to hide the logic to determine if this Tile
// has a Piece or not.
char symbol() const {
// Check if there is a Piece in this Tile using the conversion
// to bool operator here too:
if(*this)
return occ->symbol();
else
return '-'; // no Piece here
}
};
// add support to stream a Tile to an ostream
std::ostream& operator<<(std::ostream& os, const Tile& t) {
return os << t.symbol();
}
class Board {
private:
Tile tiles[2][2];
public:
Board() {
// using the added operator() further down
(*this)(0,0) = new One;
(*this)(0,1) = new Two;
(*this)(1,1) = new One;
}
// Note that cols and rows in arrays are usually seen as reversed.
// tiles[2][2] usually means:
// tiles[<rows>=2][<cols>=2]
// getTile() replacements - the interface here is still (col, row)
// but it accesses the tiles[][] using the common form (row, col)
Tile& operator()(int c, int r) { return tiles[r][c]; }
Tile const& operator()(int c, int r) const { return tiles[r][c]; }
// moving by swapping tiles
void move(int c1, int r1, int c2, int r2) {
// using operator() and the standard function std::swap
std::swap((*this)(c1, r1), (*this)(c2, r2));
}
};
// Add a stream operator to not have to call print() explicitly when streaming
std::ostream& operator<<(std::ostream& os, const Board& b) {
for(int r = 0; r < 2; r++) {
for(int c = 0; c < 2; c++) {
// Use "Board::operator() const" and stream support for returned
// Tile.
os << b(c, r);
}
os << '\n';
}
os << '\n';
return os;
}
int main() {
// no need to "new" anything:
Board oldBoard;
Board newBoard(oldBoard); // use copy constructor
// use streaming operators
std::cout << "Old board: \n" << oldBoard;
std::cout << "New board: \n" << newBoard;
// using the getTile() replacement, Board::operator():
std::cout << "New board # tile 1,0: " << newBoard(1, 0) << " before move\n";
newBoard.move(0, 0, 1, 0);
std::cout << "New board # tile 1,0: " << newBoard(1, 0) << " after move\n\n";
std::cout << "New board after move:\n" << newBoard;
newBoard = oldBoard; // copy assignment operator
std::cout << "New board after reinit:\n" << newBoard;
}
Be aware of that there are many things inside example that would be done in a slightly different (more efficient) way in C++11 and later where std::unique_ptr, move semantics and extended initializer lists were added.
I want Swap the name (i.e. string in cName[]) of the two cats using the pointer approach.
However I want to Only swap the name, NOT the object.
Am I correct?
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string.h>
using namespace std;
class CAT
{
public:
CAT(char * firstname) { strncpy(cName, firstname, 79); }
~CAT() { ; }
char * getName() { return cName; }
void setName(char *nameinput) { strncpy(cName, nameinput, 79); }
private:
char cName[80];
};
void nameSwap(CAT *CatA, CAT *CatB)
{
char testing[] = "testing";
CAT temp =CAT(testing);
temp = *CatA;
*CatA = *CatB;
*CatB = temp;
}
int main()
{
char Taby[] = "Taby";
char Felix[] = "Felix";
CAT pA = CAT(Taby);
CAT pB = CAT(Felix);
cout << "The inital name pA is " << pA.getName() << " and pA is" << pB.getName() << endl;
nameSwap(&pA, &pB);
cout << "After approach" << endl;
cout << "The name pA is " << pA.getName() << " and " << pB.getName() << endl;
system("PAUSE");
return 0;
}
You are actually swapping the whole objects, not only the name of the CAT.
If you only want to swap the name, you need to access the cName member in a similar way as you are doing for the objects. You'd also need permission to access to the cName member in such a swap function, which a function outside won't have since cName is private. Make the swap function a member of your class:
class CAT
{
public:
CAT(const char* firstname) { strncpy(cName, firstname, 80); }
~CAT() {}
const char* getName() const { return cName; }
void setName(const char *nameinput) { strncpy(cName, nameinput, 80); }
void swapName(CAT& CatB)
{
char tmp[80];
strncpy(tmp, CatB.cName, 80);
strncpy(CatB.cName, cName, 80);
strncpy(cName, tmp, 80);
}
private:
char cName[80];
// other CAT attributes won't be affected by the name swap
};
And call it like this
pA.swapName(pB); // or pB.swapName(pA); - same result
But consider using std::string instead of char[]. You'll soon find C++ strings much easier to work with and also, when swapping those, only the pointers to the underlying memory is swapped, so it's more effective.
std::string one;
std::string two;
one.swap(two);
Edit: As per request, I added a version using pointers.
I made it in a haste and haven't debugged it so I've probably made a lot of mistakes. First, I made a new class called wong_string that will hold the name and any other attributes suiteable for strings.
#include <stdexcept>
#include <cstring>
class wong_string {
char* m_data;
static char* duplicate(const char* str) {
size_t len = std::strlen(str)+1;
char* rv = new char[len];
std::memcpy(rv, str, len);
return rv;
}
public:
// default constructor: wong_string howdy1;
wong_string() : m_data(nullptr) {}
// conversion constructor: wong_string howdy2("value2");
wong_string(const char* cstr) :
m_data(duplicate(cstr))
{}
// copy constructor: wong_string howdy3 = howdy2;
wong_string(const wong_string& rhs) : wong_string(rhs.m_data) {}
// move constructor: wong_string howdy4 = wong_string("value4");
wong_string(wong_string&& rhs) : m_data(rhs.m_data) {
rhs.m_data = nullptr;
}
// copy assignment operator: (wong_string howdy5;) howdy5 = howdy4;
wong_string& operator=(const wong_string& rhs) {
if(this!=&rhs) {
char* tmp = duplicate(rhs.m_data);
if(m_data) delete []m_data;
m_data = tmp;
}
return *this;
}
// copy assignment operator from c string
wong_string& operator=(const char* rhs) {
*this = wong_string(rhs);
return *this;
}
// move assignment operator: (wong_string howdy6;) howdy6 = wong_string("value6");
wong_string& operator=(wong_string&& rhs) {
if(this!=&rhs) {
m_data = rhs.m_data;
rhs.m_data = nullptr;
}
return *this;
}
// destructor, free memory allocated by duplicate(), if any
~wong_string() {
if(m_data) delete []m_data;
}
// comparisons
bool operator==(const wong_string& rhs) const {
return strcmp(m_data, rhs.m_data)==0;
}
bool operator!=(const wong_string& rhs) const {
return !(*this==rhs);
}
// conversion to a normal c string
operator char const* () const { return m_data; }
// output stream operator
friend std::ostream& operator<<(std::ostream&, const wong_string&);
// input stream operator - not implemented yet
};
with that in place, your CAT can be made into something like this:
class CAT
{
public:
CAT(const char* firstname, const char* nickname=nullptr) :
cName(firstname),
cNickName(nickname?nickname:firstname)
{}
~CAT() {}
const char* getName() const { return cName; }
void setName(const char *nameinput) { cName=nameinput; }
void swapName(CAT& CatB)
{
std::swap(cName, CatB.cName);
}
private:
wong_string cName; // Madame Florence Jenkins III
// other CAT attributes won't be affected by the name swap
wong_string cNickName; // Ms. Miao
};
So, there you have it. Pointers galore...
so basically I have some c++ code in VS2013 that looks like this
#include "stdafx.h"
#include <malloc.h>
#include <stdio.h>
class Test_Class {
public:
Test_Class() {
printf("In Test_Class()\n");
allocated_array = (int*)malloc(sizeof(int) * 64);
printf("Allocated %p\n", allocated_array);
}
~Test_Class() {
printf("In ~Test_Class()\n");
printf("Freeing %p\n", allocated_array);
free(allocated_array);
printf("Freed %p\n", allocated_array);
}
private:
int* allocated_array;
};
class Holder {
public:
Holder() {
printf("In Holder()\n");
m_test_class = Test_Class();
}
~Holder() {
printf("In ~Holder()\n");
}
private:
Test_Class m_test_class;
};
class Game {
public:
Game() {
printf("In Game()\n");
m_holder = Holder();
}
~Game() {
printf("In ~Game()");
}
private:
Holder m_holder;
};
int main()
{
printf("In main()\n");
Game game = Game();
return 0;
}
That when ran, gives me this output:
What I'm wondering is, why is the destructor of the same Test_Class object getting called twice before it crashes (due to trying to free the same pointer twice). I went through with the debugger, to make sure it wasn't just a new instance of the class that had been given the same pointer as the other object, and sure enough it was the exact same object.
I understand that since the Test_Class object is a member of Holder, that it would create a Test_Class object, then create another one and destroy the old one (which it seems to do), but this weird behaviour of calling the destructor on the same seems to occur when I make a member of type Holder in the Game class. Obviously there's something I'm missing.
The reason is, that your compiler is not able to eliminate the copy assignment Game game = Game();.
The correct code would be Game game;.
What your code does is to construct an object as rvalue, assign it to a new object game that is a lvalue. So in this line Game game = Game(); two objects are constructed and one of them is immediately destructed after assignment.
Edit:
The same holds for m_Holder and so on - of course.
You might benefit from instrumenting your class to see what's happening. A technique I often use is to create a specific instrumentation class with static counters for each significant event. Here's an example that is little more than a wrapper around a numeric type (specifically double in this case), but it illustrates the idea:
class Goofy
{
private:
double num;
public:
Goofy(double n = 0) : num(n) { ++constructions; }
Goofy(const Goofy &g2) : num(g2.num) { ++copyconstructions; }
Goofy(const Goofy &&g2) : num(g2.num) { ++moves; }
~Goofy() { ++destructions; }
Goofy &operator=(const Goofy &g2) { num = g2.num; return *this; }
Goofy &operator-=(const Goofy &g2) { num -= g2.num; return *this; }
Goofy &operator+=(const Goofy &g2) { num += g2.num; return *this; }
// none of the code below is needed by the new version of the function
Goofy &operator*=(const Goofy &g2) { num *= g2.num; return *this; }
friend std::ostream &operator<<(std::ostream &out, const Goofy &g2) {
return out << g2.num;
}
static void report(int line) {
std::cout << "At line " << line
<< "\nconstructions = " << Goofy::constructions
<< "\n copies = " << Goofy::copyconstructions
<< "\n moves = " << Goofy::moves
<< "\n destructions = " << Goofy::destructions
<< "\n existing = " << Goofy::constructions +
Goofy::copyconstructions + Goofy::moves -
Goofy::destructions
<< '\n';
}
static long constructions;
static long copyconstructions;
static long moves;
static long destructions;
};
long Goofy::constructions = 0;
long Goofy::copyconstructions = 0;
long Goofy::moves = 0;
long Goofy::destructions = 0;
Here's an example of how it was used: https://codereview.stackexchange.com/questions/56532/kahan-summation/56592#56592
There's a lot wrong with your code, but I'm going to go with it anyways. You need to (at a minimum) implement the copy constructor and copy assignment operator. I would use new, delete and swap since this is C++ and not C. Something like this:
Test_Class() {
allocated_array = new int[64];
}
~Test_Class() {
delete[] allocated_array;
}
Test_Class(const Test_Class& rhs)
{
allocated_array = new int[64];
std::copy(&rhs.allocated_array[0], &rhs.allocated_array[0] + 64, &allocated_array[0]);
}
Test_Class& operator=(const Test_Class rhs)
{
if (this != &rhs)
{
Test_Class(rhs).swap(*this);
}
return *this;
}
void swap(Test_Class & s) throw()
{
std::swap(this->allocated_array, s.allocated_array);
}
I have a class:
class taphop
{
public:
taphop();
~taphop();
taphop(const list&);
taphop& operator=(const taphop&);
taphop operator+(const int&);
taphop operator+(const taphop&);
};
In main, I can't using multiple parameters:
main()
{
taphop lmc=lmc+2+5+3+2; // Error;
lmc=lmc+3+5+2; // Error;
int a=a+1+2+4+5; // Not error;
a=a+1+2+4+5; // Not error;
return 0;
}
One thing for sure. Below is undefined.
taphop lmc=lmc+2+5+3+2;
As operator+ would be called on the carcass of supposed-to-be-fully-constructed object in expression
lmc+2+5+3+2
In addition to using lmc to initialize lmc, you just need to read the error messages the compiler is giving you. Here is my take on what you might be trying to do:
class taphop
{
int value;
public:
taphop(const int x = 0) :value(x) {} // default value of 0
~taphop() {}
int getvalue() const { return value; }
taphop& operator=(const taphop &r) { value = r.value; return *this; }
taphop operator+(const int x) { return taphop(value + x); }
taphop operator+(const taphop &r) { return taphop(value + r.value); }
};
int main()
{
taphop lmc = taphop(0) + 2 + 5 + 3 + 2;
std::cout << lmc.getvalue() << std::endl; // prints 12
lmc = lmc + 3 + 5 + 2;
std::cout << lmc.getvalue() << std::endl; // prints 22
return 0;
}