cpmv.h
#ifndef CPMV_H_
#define CPMV_H_
#include<iostream>
class Cpmv
{
public:
struct Info// info is only a self-defined type, has no contents in Cpmv
{
std::string qcode;
std::string zcode;
};
private:
Info *pi;
public:
Cpmv();
Cpmv(std::string q, std::string z);
Cpmv(const Cpmv & cp);
Cpmv(Cpmv && mv);
~Cpmv();
Cpmv & operator=(const Cpmv & cp);
Cpmv & operator=(Cpmv && mv);
Cpmv operator+(const Cpmv & obj) const;
void Display() const;
};
#endif
cpmv.cpp
#include<iostream>
#include"cpmv.h"
#include<string>
Cpmv::Cpmv() :pi(nullptr)
{
std::cout << "default constructor is revolked.\n";
pi = new Info;
pi->qcode = "none";
pi->zcode = "none";
}
Cpmv::Cpmv(std::string q, std::string z)
{
std::cout << "\nCpmv(std::string q, std::string z) is revolked.\n";
pi = new Info;
pi->qcode = q;// class "string" has its own method to create new contents at heap zone
pi->zcode = z;
}
Cpmv::Cpmv(const Cpmv & cp)// also can be: pi->qcode(cp.pi->qcode)
{
std::cout << "\nCpmv(const Cpmv & cp) is revolked.\n";
pi = new Info;
pi->qcode = cp.pi->qcode;// cp's contents still exist,pi just made a copy of it
pi->zcode = cp.pi->zcode;
}
Cpmv::Cpmv(Cpmv && mv)
{
std::cout << "\nCpmv(Cpmv && mv) is revolked.\n";
pi = mv.pi;// steal rvalue's address
mv.pi = nullptr;
}
Cpmv::~Cpmv()
{
std::cout << "\n~Cpmv() is revolked.\n";
delete pi;
}
Cpmv & Cpmv::operator=(const Cpmv & cp)
{
std::cout << "\noperator=(Cpmv& mv) is revolked.\n";
if (pi == cp.pi)
{
std::cout << "\nCan't use assignment operator, as the two points to same memory address.\n";
return *this;// requre to return a value
}
pi = new Info;
pi->qcode = cp.pi->qcode;
pi->zcode = cp.pi->zcode;
return *this;
}
Cpmv & Cpmv::operator=(Cpmv && mv)
{
if (pi == mv.pi)
{
std::cout << "\nCan't use assignment operator, as the two points to same memory address.\n";
return *this;// requre to return a value
}
else
{
std::cout << "\noperator=(Cpmv&& mv) is revolked.\n";
pi = mv.pi;// steal
mv.pi = nullptr;
}
}
Cpmv Cpmv::operator+(const Cpmv & obj) const
{
std::cout << "\noperator+ is revolked.\n";
// default constructor must make pi has real contents,
//only a pi points to nullptr can't be assigned value
Cpmv temp;
temp.pi->qcode = pi->qcode + obj.pi->qcode;
temp.pi->zcode = pi->zcode + obj.pi->zcode;
return temp;
//std::string tempq= pi->qcode + obj.pi->qcode;
//::string tempz = pi->zcode + obj.pi->zcode;
//return Cpmv(tempq, tempz);// use previous constructor
}
void Cpmv::Display() const
{
if (pi == nullptr)
std::cout << "\nThis is a empty object.\n";
else
{
std::cout << "Object details: \n"
<< "qcode: " << pi->qcode << std::endl
<< "zcode: " << pi->zcode << std::endl;
}
}
main.cpp
#include<iostream>
#include"cpmv.h"
using namespace std;
int main()
{
cout << "\nCpmv c1\n";
Cpmv c1;// default constructor
c1.Display();
cout << "\nCpmv c2(\"qqqq\", \"zzzz\")\n";
Cpmv c2("qqqq", "zzzz");
c2.Display();
cout << "\nCpmv c3(c2)\n";
Cpmv c3(c2);// copy constructor
c3.Display();
cout << "\nCpmv c4(c2 + c3)\n";
Cpmv c4(c2 + c3);// use operator+,and move copy constructor
c4.Display();
cout << "\nCpmv c5 = c4\n";
Cpmv c5 = c4;// assignment operator
c5.Display();
cout << "\nc1 = c4 + c5\n";
c1 = c4 + c5;
// move assignment operator. temp is the result of c4+c5, c1 will steam from temp
// after statement block expired,it will revolk destructor which will destruct a nullptr
c1.Display();
std::cin.get();
return 0;
}