A Singer类
答案:
#include<iostream>
using namespace std;
class Singer{
private:
string name;
char sex;
int age;
double score;
public:
string getName();
friend istream & operator>>(istream & in,Singer & s);
friend ostream & operator<<(ostream & out,Singer & s);
friend bool operator>(Singer & s1,Singer & s2);
friend bool operator==(Singer & s1,Singer & s2);
};
string Singer::getName()
{
return this->name;
}
istream & operator>>(istream & in,Singer & s)
{
in>>s.name>>s.sex>>s.age>>s.score;
return in;
}
ostream & operator<<(ostream & out,Singer & s)
{
out<<s.name<<" "<<s.sex<<" "<<s.age<<" "<<s.score;
return out;
}
bool operator>(Singer & s1,Singer & s2)
{
if(s1.score>s2.score)
return true;
else
return false;
}
bool operator==(Singer & s1,Singer & s2)
{
if(s1.score==s2.score)
return true;
else
return false;
}
int main()
{
Singer s1,s2;
cin>>s1>>s2;
cout<<s1<<"\n"<<s2<<endl;
if(s1>s2)
cout<<s1.getName()<<"'s score is higher than "<<s2.getName()<<"'s.\n";
else if(s1==s2)
cout<<s1.getName()<<"'s score is equal to "<<s2.getName()<<"'s.\n";
else
cout<<s1.getName()<<"'s score is lower than "<<s2.getName()<<"'s.\n";
return 0;
}
重要知识点:
简单运算符重载。
B Sales_data类
答案:
#include<iostream>
using namespace std;
class Sales_data {
//依次输入书号、销量和收入
friend istream & operator>>(istream&, Sales_data &);
//依次输出书号、销量、收入和均价
friend ostream & operator<<(ostream &, const Sales_data &);
friend bool operator==(const Sales_data &, const Sales_data &);
friend bool operator!=(const Sales_data &, const Sales_data &);
// for "+", assume that both objects refer to the same book
friend Sales_data operator+(const Sales_data &, const Sales_data &);
public:
Sales_data(): units_sold(0), revenue(0.0) {}
Sales_data(const string & s, unsigned n, double r): bookNo(s), units_sold(n), revenue(r) {}
string get_bookNo() const;
// for "+=", assume that both objects refer to the same book
Sales_data & operator+=(const Sales_data &);
private:
double avg_price() const; //均价,等于收入除以销量
string bookNo; //书号
unsigned units_sold; //销量
double revenue; //收入
};
double Sales_data::avg_price() const
{
return revenue/units_sold;
}
istream & operator>>(istream& is,Sales_data & s)
{
is>>s.bookNo>>s.units_sold>>s.revenue;
return is;
}
ostream & operator<<(ostream & os, const Sales_data & s)
{
os<<s.bookNo<<" "<<s.units_sold<<" "<<s.revenue<<" "<<s.avg_price();
return os;
}
bool operator==(const Sales_data & s1, const Sales_data & s2)
{
if(s1.bookNo==s2.bookNo)
return 1;
else
return 0;
}
bool operator!=(const Sales_data &s1, const Sales_data &s2)
{
if(s1.bookNo==s2.bookNo)
return 0;
else
return 1;
}
Sales_data operator+(const Sales_data &s1, const Sales_data &s2)
{
Sales_data ts;
ts.bookNo=s1.bookNo;
ts.units_sold=s1.units_sold+s2.units_sold;
ts.revenue=s1.revenue+s2.revenue;
return ts;
}
string Sales_data::get_bookNo() const
{
return this->bookNo;
}
Sales_data & Sales_data::operator+=(const Sales_data & s)
{
this->revenue+=s.revenue;
this->units_sold+=s.units_sold;
return *this;
}
int main(){
Sales_data item1,item2;
while(cin>>item1>>item2){
cout<<item1<<"\n"<<item2<<"\n";
if(item1==item2)
cout<<item1.get_bookNo()<<" equals "<<item2.get_bookNo()<<"\n";
if(item1!=item2)
cout<<item1.get_bookNo()<<" doesn't equal "<<item2.get_bookNo()<<"\n";
cout<<(item1+item2)<<"\n";
item1 += item2;
cout<<item1<<"\n";
}
return 0;
}
重要知识点:
麻烦一点的简单运算符重载。
C Complex类
答案:
#include<iostream>
using namespace std;
class Complex
{
private:
double x;
double y;
public:
Complex(double x = 0.0, double y = 0.0);
Complex & operator+=(const Complex &);
Complex & operator-=(const Complex &);
Complex & operator*=(const Complex &);
Complex & operator/=(const Complex &);
friend Complex operator+(const Complex &, const Complex &);
friend Complex operator-(const Complex &, const Complex &);
friend Complex operator*(const Complex &, const Complex &);
friend Complex operator/(const Complex &, const Complex &);
friend bool operator==(const Complex &, const Complex &);
friend bool operator!=(const Complex &, const Complex &);
friend ostream & operator<<(ostream &, const Complex &);
friend istream & operator>>(istream &, Complex &);
};
Complex::Complex(double x, double y)
{
this->x=x;
this->y=y;
}
Complex & Complex::operator+=(const Complex & c)
{
this->x+=c.x;
this->y+=c.y;
return *this;
}
Complex & Complex::operator-=(const Complex & c)
{
this->x-=c.x;
this->y-=c.y;
return *this;
}
//需要将临时变量保存原始数值,然后再进行计算操作
Complex & Complex::operator*=(const Complex & c)
{
double tx=x;
double ty=y;
x=tx*c.x-ty*c.y;
y=tx*c.y+ty*c.x;
return *this;
}
Complex & Complex::operator/=(const Complex & c)
{
double tx=x;
double ty=y;
this->x=(tx*c.x+ty*c.y)/(c.x*c.x+c.y*c.y);
this->y=(ty*c.x-tx*c.y)/(c.x*c.x+c.y*c.y);
return *this;
}
Complex operator+(const Complex &c1, const Complex &c2)
{
Complex tc;
tc.x=c1.x+c2.x;
tc.y=c1.y+c2.y;
return tc;
}
Complex operator-(const Complex &c1, const Complex &c2)
{
Complex tc;
tc.x=c1.x-c2.x;
tc.y=c1.y-c2.y;
return tc;
}
Complex operator*(const Complex &c1, const Complex &c2)
{
Complex tc;
tc.x=c1.x*c2.x-c1.y*c2.y;
tc.y=c1.x*c2.y+c1.y*c2.x;
return tc;
}
Complex operator/(const Complex &c1, const Complex &c2)
{
Complex tc;
tc.x=(c1.x*c2.x+c1.y*c2.y)/(c2.x*c2.x+c2.y*c2.y);
tc.y=(c1.y*c2.x-c1.x*c2.y)/(c2.x*c2.x+c2.y*c2.y);
return tc;
}
bool operator==(const Complex &c1, const Complex &c2)
{
if(c1.x==c2.x)
return 1;
else
return 0;
}
bool operator!=(const Complex &c1, const Complex &c2)
{
if(c1.x==c2.x)
return 0;
else
return 1;
}
ostream & operator<<(ostream &os, const Complex &c)
{
os<<c.x<<" + "<<c.y<<"i";
return os;
}
istream & operator>>(istream &is, Complex &c)
{
is>>c.x>>c.y;
return is;
}
int main()
{
Complex c1, c2;
cin >> c1 >> c2;
cout << "c1 = " << c1 << "\n" << "c2 = " << c2 << endl;
cout << "c1+c2 = " << c1 + c2 << endl;
cout << "c1-c2 = " << c1 - c2 << endl;
cout << "c1*c2 = " << c1 * c2 << endl;
cout << "c1/c2 = " << c1 / c2 << endl;
cout << (c1 += c2) << endl;
cout << (c1 -= c2) << endl;
cout << (c1 *= c2) << endl;
cout << (c1 /= c2) << endl;
cout << (c1 == c2) << " " << (c1 != c2) << endl;
return 0;
}
重要知识点:
很经典全面的运算符重载实例,注意一下实现乘除法时需要将临时变量保存原始数值,然后再进行计算操作。
D String类 (重点学习)
描述:
实现以下String类:
class String
{
private:
char * s;
public:
String();
String(const char *);
String(const String &);
~String();
String & operator=(const char *);
String & operator=(const String &);
String operator+(const char *);
String operator+(const String &);
String & operator+=(const char *);
String & operator+=(const String &);
friend istream & operator>>(istream &, String &);
friend ostream & operator<<(ostream &, const String &);
friend bool operator==(const String &, const char *);
friend bool operator==(const String &, const String &);
friend bool operator!=(const String &, const char *);
friend bool operator!=(const String &, const String &);
};
使用以下main函数进行测试:
int main()
{
String s;
s += “hello”;
cout<<s<<endl;
String s1(“String1”);
String s2("copy of ");
s2 += “String1”;
cout << s1 << “\n” << s2 << endl;
String s3;
cin >> s3;
cout << s3 << endl;
String s4(“String4”), s5(s4);
cout << (s5 == s4) << endl;
cout << (s5 != s4) << endl;
String s6("End of "), s7(“my string.”);
s6 += s7;
cout << s6 << endl;
return 0;
}
输入:
s3的值
输出:
见示例与主函数
输入样例:
String3
输出样例:
hello
String1
copy of String1
String3
1
0
End of my string.
答案:
#include<iostream>
#include<cstring>
using namespace std;
class String
{
private:
char* s;
public:
String();
String(const char*);
String(const String&);
~String();
String& operator=(const char*);
String& operator=(const String&);
String operator+(const char*);
String operator+(const String&);
String& operator+=(const char*);
String& operator+=(const String&);
friend istream& operator>>(istream&, String&);
friend ostream& operator<<(ostream&, const String&);
friend bool operator==(const String&, const char*);
friend bool operator==(const String&, const String&);
friend bool operator!=(const String&, const char*);
friend bool operator!=(const String&, const String&);
};
String::String()
{
s = new char[1];
s[0]='\0';
//s=NULL;
}
String::String(const char* tc)
{
s = new char[strlen(tc) + 1];
strcpy(s, tc);
}
String::String(const String& ts)
{
s = new char[strlen(ts.s) + 1];
strcpy(s, ts.s);
}
String::~String()
{
delete[] s;
}
String& String::operator=(const char* tc)
{
s = new char[strlen(tc) + 1];
strcpy(s, tc);
return *this;
}
String& String::operator=(const String& ts)
{
s = new char[strlen(ts.s) + 1];
strcpy(s, ts.s);
return *this;
}
String String::operator+(const char* tc)
{
String news;
news.s = new char[strlen(s) + strlen(tc) + 1];
strcpy(news.s, s);
strcat(news.s, tc);
return news;
}
String String::operator+(const String& ts)
{
String news;
news.s = new char[strlen(s) + strlen(ts.s) + 1];
strcpy(news.s, s);
strcat(news.s, ts.s);
return news;
}
String& String::operator+=(const char* tc)
{
char* news = new char[strlen(s) + strlen(tc) + 1];
strcpy(news, s);
strcat(news, tc);
delete[] s;
s = news;
return *this;
}
String& String::operator+=(const String& ts)
{
char* news = new char[strlen(s) + strlen(ts.s) + 1];
strcpy(news, s);
strcat(news, ts.s);
delete[] s;
s = news;
return *this;
}
istream& operator>>(istream& is, String& ts)
{
char temp[100];
is >> temp;
delete[] ts.s;
ts.s = new char[strlen(temp) + 1];
strcpy(ts.s, temp);
return is;
}
ostream& operator<<(ostream& os, const String& ts)
{
os << ts.s;
return os;
}
bool operator==(const String& ts, const char* tc)
{
return (strcmp(ts.s, tc) == 0);
}
bool operator==(const String& ts1, const String& ts2)
{
return (strcmp(ts1.s, ts2.s) == 0);
}
bool operator!=(const String& ts, const char* tc)
{
return !(strcmp(ts.s, tc) == 0);
}
bool operator!=(const String& ts1, const String& ts2)
{
return !(strcmp(ts1.s, ts2.s) == 0);
}
int main()
{
String s;
s += "hello";
cout << s << endl;
String s1("String1");
String s2("copy of ");
s2 += "String1";
cout << s1 << "\n" << s2 << endl;
String s3;
cin >> s3;
cout << s3 << endl;
String s4("String4"), s5(s4);
cout << (s5 == s4) << endl;
cout << (s5 != s4) << endl;
String s6("End of "), s7("my string.");
s6 += s7;
cout << s6 << endl;
return 0;
}
重要知识点:
1.首先注意到成员是个字符指针,要想到new与delete、浅拷贝与深拷贝相关知识。
2.无参构造函数:
String::String()
{
s = new char[1];
s[0]='\0';
//s=NULL;
}
要为类的成员变量s动态分配内存来存储字符串。由于字符串是以\0结尾的字符数组,
所以需要为s分配一个长度为1的字符数组,并将数组的第一个元素设为字符’\0’,以表示空字符串的结束。
这样可以确保s成员变量始终以空字符串结尾,从而正确表示一个空的String对象。
而s=NULL不行:因为String类表示的是一个字符串对象,
如果将s赋值为NULL,那么s将指向空地址,而不是一个空字符串。这样会导致后续对s操作时出现错误。
3.两个拷贝构造函数:
String::String(const char* tc)
{
s = new char[strlen(tc) + 1];
strcpy(s, tc);
}
String::String(const String& ts)
{
s = new char[strlen(ts.s) + 1];
strcpy(s, ts.s);
}
首先为s申请足够的空间,再通过strcpy()实现字符串的深拷贝。
4.注意析构函数中使用delete。
5.对=重载时要删除原来的值;
6.对+重载时逻辑为创造一个新对象,strcpy前一个字符串,再strcat加上后一个字符串。最后返回这个新对象。
7.+=与+区别:
创建的是char* 而非string类对象(最后直接赋予String.s);
s = news;前delete原先对象。
最后返回的是自己。
8.>>的重载:
直接is>>ts.s也能通过但并不符合常理,应该按上文写法;
9.strcmp的返回值;(为0为相等)
E CheckedPtr
答案:
#include<iostream>
using namespace std;
class CheckedPtr
{
public:
CheckedPtr(int * b, int * e) : beg(b), end(e), curr(b) { }
CheckedPtr & operator ++(); // prefix ++
CheckedPtr & operator --(); // prefix --
CheckedPtr operator ++(int); // postfix ++
CheckedPtr operator --(int); // postfix --
int * GetBeg();
int * GetEnd();
int * GetCurr();
private:
int * beg; // pointer to beginning of the array
int * end; // one past the end of the array
int * curr; // current position within the array
};
CheckedPtr & CheckedPtr::operator ++()
{
++curr;
return *this;
}
CheckedPtr & CheckedPtr::operator --()
{
--curr;
return *this;
}
CheckedPtr CheckedPtr::operator ++(int)
{
CheckedPtr temp = *this;
++curr;
return temp;
}
CheckedPtr CheckedPtr::operator --(int)
{
CheckedPtr temp = *this;
--curr;
return temp;
}
int * CheckedPtr::GetBeg()
{
return beg;
}
int * CheckedPtr::GetEnd()
{
return end;
}
int * CheckedPtr::GetCurr()
{
return curr;
}
int main(){
int n;
cin>>n;
int * array = new int[n];
for(int i=0;i<n;i++)
cin>>array[i];
CheckedPtr cp(array, array+n);
for(;cp.GetCurr()<cp.GetEnd();cp++)
cout<<*cp.GetCurr()<<" ";
cout<<endl;
for(--cp;cp.GetCurr()>cp.GetBeg();cp--)
cout<<*cp.GetCurr()<<" ";
cout<<*cp.GetCurr()<<endl;
delete [] array;
return 0;
}
重要知识点:
这里主要关注前缀++/–与后缀++/–的写法及其区别。