引自C++Primer第四版中的类的例子,稍作修改并啰嗦了一些注释,用来回顾C++面向对象的基本知识。 #include<iostream> #include<string> using namespace std; //vc++6.0的问题,友员要前向声明 class Sales_item; istream& operator>>(istream&,Sales_item&); ostream& operator<<(ostream&,const Sales_item&); bool operator==(const Sales_item&,const Sales_item&); bool operator!=(const Sales_item&,const Sales_item&); class Sales_item{ /* 需要访问private数据的操作应设为friend */ //为了与标准库兼容,不能设为类的成员函数,否则此函数第一个形参将默认为隐含的this friend istream& operator>>(istream&,Sales_item&); friend ostream& operator<<(ostream&,const Sales_item&); //两个操作数的对称操作符重载,通常设为非成员函数 friend bool operator==(const Sales_item&,const Sales_item&); friend bool operator!=(const Sales_item&,const Sales_item&); public: //构造函数的两个版本 explicit Sales_item():units_sold(0),revenue(0.0)//explicit关键字声明的构造函数可以防止隐式转换,见main()中例子 { cout<<"structor WITHOUT parameters"<<endl; } Sales_item(string book): isbn(book),units_sold(0),revenue(0.0) //按数据声明的顺序进行初始化 { cout<<"structor with parameters"<<endl; } /*这里不定义自己的复制构造函数,默认采用合成的版本, 当有数据成员表示在构造函数中分配资源时(例如指针),必须自己定义复制构造函数*/ /*复合赋值操作符应定义为类的成员,但不是必须这样做 (赋值=、下标[]、调用()、成员访问箭头->这些操作符必须定义为成员函数)*/ //类定义了+操作符,逻辑上也应该定义+=操作符 Sales_item& operator+=(const Sales_item&); double avg_price() const; //const 成员函数不能改变数据成员,唯一的例外是mutable(可变数据成员) bool same_isbn(const Sales_item &rhs) const //类内部定义的函数默认为inline { return isbn == rhs.isbn; } ~Sales_item(){cout<<"destructor run"<<endl;}; //析构函数 private: string isbn; unsigned units_sold; double revenue; }; inline double Sales_item::avg_price() const //可以在类内部声明时或类外部定义时说明成员函数为inline { if(units_sold) return revenue/units_sold; else return 0; } istream& operator>>(istream& in,Sales_item& s)//输入操作符的重载,符合标准库 { double price; in>>s.isbn>>s.units_sold>>price; if(in) //输入无错误时才处理数据 s.revenue=s.units_sold*price; else //否则应该重设类的所有数据 s=Sales_item(); return in; } ostream& operator<<(ostream& out,const Sales_item& s)//输出操作符的重载,符合标准库 { //格式应该在必要的前提下尽可能少,更具体的格式由用户控制 out<<s.isbn<<"/t"<<s.units_sold<<"/t"<<s.revenue<<"/t"<<s.avg_price(); return out; } Sales_item& Sales_item::operator +=(const Sales_item& rhs) //复合赋值操作符应返回左操作数的引用(隐含的this) { units_sold += rhs.units_sold; revenue +=rhs.revenue; return *this; } /* 算术操作符、关系操作符、相等操作符、位操作符最好定义为普通非成员函数 */ //利用复合赋值实现加法操作,无需再对每一数据成员单独操作,也不需要声明为友员 Sales_item operator+(const Sales_item& lhs,const Sales_item& rhs)//形参为const引用避免复制 { Sales_item ret(lhs); ret +=rhs; return ret; } //相等操作符的定义 inline bool operator==(const Sales_item& lhs,const Sales_item& rhs) { return lhs.units_sold==rhs.units_sold && lhs.revenue==rhs.revenue && lhs.same_isbn(rhs); } //利用相等操作符定义!=操作符 inline bool operator!=(const Sales_item& lhs,const Sales_item& rhs) { return !(lhs==rhs); } int main() { string book("999-9"); Sales_item item1,item2; cin>>item1>>item2; Sales_item item3(item2); //调用合成的复制构造函数,因为我们并没有显式定义自己的版本 Sales_item item4=item1; //不是没有定义=的重载吗?因为赋值、取地址、逗号操作符对类类型操作数有默认含义 Sales_item item5; //调用第一个不带参数的构造函数 Sales_item item6("999-9"); //调用第二个带一个参数的构造函数 if(item1 == item2) cout<<"the two items are the same"<<endl; if(item1 != item2) cout<<"the two items are not the same"<<endl; if(item1.same_isbn(item2)) { cout<<"ADD RESULT:/n"<<item1+item2<<endl; item1 +=item2; cout<<item1<<endl; } else cerr<<"CAN NOT ADD,DATA MUST REFER TO SAME ISBN"<<endl; cout<<item3<<endl; cout<<item4<<endl; cout<<item5<<endl; cout<<item6<<endl; cout<<item6.same_isbn(book)<<endl;//接受一个string的构造函数从book生成一个临时的Sales_item对象作为参数传给item6.same_isbn() //有时这并不是个好主意,可以在构造函数前加explicit来防止这种情况的发生 return 0; }