1.构造函数与析构函数
如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。
定义分成两部分,一是静态变量的初始化,二是静态函数的定义。
静态变量的初始化不能在类的定义中,但是可以在类的外部通过使用范围解析运算符
::
来重新声明静态变量从而对它进行初始化。而定义静态函数,那就与定义实例函数一样了。
静态成员的访问有以下两种方法:
使用
类型名::静态成员
格式访问;(可以将其看做是一个全局变量,只不过变量名要带上类型名::
的前缀)通过对象访问;(可以将其看做是对象中的一个实例成员)
cout << Test::HelloStr << endl; // 通过作用域运算符访问
Test::HelloStr = "World"; // 修改静态变量 HelloStr
Test t1;
cout << t1.HelloStr <<endl; // 通过对象访问
Test::Hello(); // 通过作用域运算符访问
t1.World(); // 通过对象访问
class User{
public:
string Name;
int Books=0;
static int tot_books,tot_ren;
User(string name,int books):Name(name),Books(books){
cout<<Name<<" "<<Books<<" 进入"<<endl;
tot_books+=Books;
tot_ren++;
};
~User(){
cout<<Name<<" "<<Books<<" 离开"<<endl;
tot_books-=Books;
tot_ren--;
};
static void GetState(){
cout<<"书店人数:"<<tot_ren<<",书店共享书数量:"<<tot_books<<",人均共享数量:"
<<tot_books/tot_ren<<endl;
}
};
int User::tot_books=0;
int User::tot_ren=0;
2.内部类练习
注意:牛腿的长度默认为牛高的一半
#include<string>
#include<iostream>
using namespace std;
class Cow{
public:
int weight,height;
Cow(int _weight,int _height):weight(_weight),height(_height){};
class CowLeg{
public:
string color;
int length;
CowLeg(string _color,int _length):color(_color),length(_length){};
void show(){
cout<<"牛腿的颜色是"<<color<<endl;
cout<<"牛腿的长度是"<<length<<endl;
}
};
void display(string _color){
CowLeg leg(_color,height/2);
leg.color=_color;
leg.show();
cout<<"整牛高"<<height<<endl;
cout<<"整牛重"<<weight<<endl;
}
};
3.类的书写(运算符重载)
3.1复数
class Complex{
public:
double real,image;
Complex(double r,double i):real(r),image(i){};
void Print(){
if(image>=0) cout<<real<<"+"<<image<<"i"<<endl;
else cout<<real<<image<<"i"<<endl;
}
Complex operator + (const Complex tem){
return (Complex){real+tem.real, image+tem.image};
}
Complex operator - (const Complex tem){
return (Complex){real-tem.real, image-tem.image};
}
Complex operator * (const Complex tem){
//(a+bi)(c+di)=(ac-bd)+(ad+bc)i;
return (Complex){real*tem.real-image*tem.image, real*tem.image+tem.real*image};
}
Complex operator / (const Complex tem){
double a=real,b=image,c=tem.real,d=tem.image;
//(a+bi)(c-di)/(c^2+d^2)=[(ac+bd)+(bc-ad)i]/(c^2+d^2);
return (Complex){(a*c+b*d)/(c*c+d*d),(b*c-a*d)/(c*c+d*d)};
}
};
强制类型转换调用
int a;
Int b=(Int)a;
3.2<<与>>重载
<< 和 >> 的重载一般使用 friend
class 1 Time
#include<iostream>
using namespace std;
class Time{
private:
int hour,minute,second;
public:
Time():hour(0),minute(0),second(0){};
Time(int h,int m,int s):hour(h),minute(m),second(s){};
Time operator +(const Time& b){
Time t1;
t1.hour=hour+b.hour;
t1.minute=minute+b.minute;
t1.second=second+b.second;
if(t1.second>=60)t1.second-=60,t1.minute++;
if(t1.minute>=60)t1.minute-=60,t1.hour++;
if(t1.hour>=24)t1.hour-=24;
return t1;
}
friend ostream& operator<< (ostream& os,const Time & b);
friend istream& operator>> (istream& is,Time & b);
};
ostream& operator << (ostream& os,const Time& b){
os<<b.hour<<':'<<b.minute<<':'<<b.second<<endl;
return os;
};
istream& operator >> (istream& is,Time& b){
is>>b.hour>>b.minute>>b.second;
return is;
};
class 2 Point
测试主函数
int main(){
int a,b;
cout<<"输入第一个点:"<<endl;
cin>>a>>b;
Point p1(a,b);
cout<<"输入第二个点:"<<endl;
cin>>a>>b;
Point p2(a,b);
double d=p1-p2;
cout<<p1<<"->"<<p2<<"="<<d<<endl;
return 0;
}
要求实现输出
输入第一个点:
输入第二个点:
[2,4]->[7,-1]=7.07107
答案
#include<bits/stdc++.h>
using namespace std;
class Point{
public:
int x,y;
Point(){};
Point(int _x,int _y):x(_x),y(_y){};
double operator -(const Point& p){
return sqrt(pow(x-p.x,2)+pow(y-p.y,2));
};
friend ostream& operator << (ostream&,Point);
};
ostream& operator << (ostream& os,Point p){
return os<<'['<<p.x<<','<<p.y<<']';
};
3.3分数类(fraction)
gcd 求最大公因数
#include<bits/stdc++.h>
using namespace std;
int gcd(int p,int q){
return !q ? p : gcd(q,p%q);
}
class fraction{
public:
int mol,den;// molecule denominator
//构造函数
fraction(const fraction & f2){ mol=f2.mol,den=f2.den; };
fraction(int p,int q){
if(q==0) cout<<"error"<<endl;
else {
int maxn=gcd(p,q);
p/=maxn; q/=maxn;
if(q<0){q=(-q),p=(-p);};
}
mol=p,den=q;
};
fraction():mol(1),den(1){};
fraction operator +(const fraction &f2){
// a/b + c/d=(ad+bc)/bd
int a=mol,b=den,c=f2.mol,d=f2.den;
int a1=a*d+b*c,b1=b*d;
fraction ans(a1,b1);
return ans;
};
fraction operator -(const fraction &f2){
// a/b - c/d=(ad-bc)/bd
int a=mol,b=den,c=f2.mol,d=f2.den;
int a1=a*d-b*c,b1=b*d;
fraction ans(a1,b1);
return ans;
};
fraction operator *(const fraction &f2){
// a/b * c/d=ac/bd
int a=mol,b=den,c=f2.mol,d=f2.den;
int a1=a*c,b1=b*d;
fraction ans(a1,b1);
return ans;
};
fraction operator /(const fraction &f2){
// a/b / c/d=ad/bc
int a=mol,b=den,c=f2.mol,d=f2.den;
int a1=a*d,b1=b*c;
fraction ans(a1,b1);
return ans;
};
bool operator ==(const fraction &f2){
if(mol==f2.mol && den==f2.den)return true;
return false;
};
friend istream& operator >>(istream& is,fraction & f1);
friend ostream& operator <<(istream& os,const fraction & f1);
};
istream& operator >>(istream& is,fraction & f1){
return is>>f1.mol>>f1.den;
}
ostream& operator <<(ostream& os,const fraction & f1){
if(f1.den==1) return os<<f1.mol;
return os<<f1.mol<<"/"<<f1.den;
}
int main(){
fraction f1,f2;
cout<<"请输入第一个分数:"<<endl;
cin>>f1;
cout<<"请输入第二个分数:"<<endl;
cin>>f2;
cout<<"加法结果:"<<endl; cout<<f1+f2<<endl;
cout<<"减法结果:"<<endl; cout<<f1-f2<<endl;
cout<<"乘法结果:"<<endl; cout<<f1*f2<<endl;
cout<<"除法结果:"<<endl; cout<<f1/f2<<endl;
if(f1==f2)cout<<"两个分数相等!"<<endl;
else cout<<"两个分数不相等!"<<endl;
return 0;
}
3.4 Intset
测试主函数
int main(){
IntSet A; A.add(3); A.add(5); A.add(1);
cout<<"Set A"<<endl;
A.show(); A.del(0);
cout<<"Set A-"<<endl; A.show();
IntSet B; B.add(5); B.add(4);
cout<<"Set B"<<endl; B.show();
cout<<"Set A+B"<<endl; (A+B).show(); //并
cout<<"Set A-B"<<endl; (A-B).show(); //差
cout<<"Set A*B"<<endl; (A*B).show(); //交
IntSet C=A; cout<<"Set C"<<endl; C.show();
A-=B; A.show(); //实现-=
}
实现如下输出
Set A
show all node in the link:
1) 3
2) 5
3) 1
the number to be delted is not in the set!Set A-
show all node in the link:
1) 3
2) 5
3) 1
Set B
show all node in the link:
1) 5
2) 4
Set A+B
The num is in the set!
show all node in the link:
1) 5
2) 4
3) 3
4) 1
Set A-B
Delete 5!
show all node in the link:
1) 3
2) 1
Set A*B
Delete 3!
Delete 1!
show all node in the link:
1) 5
Set C
show all node in the link:
1) 3
2) 5
3) 1
Delete 5!
show all node in the link:
1) 3
2) 1
#include<bits/stdc++.h>
using namespace std;
class IntSet{
public:
vector<int> ar;
IntSet(){};
IntSet(const IntSet& a){ar=a.ar;};
void add(int a){ ar.push_back(a); };
void show(){
cout<<"show all node in the link:"<<endl;
for(int i=0;i<ar.size();i++)
cout<<i+1<<") "<<ar[i]<<endl;
}
void del(int a){
if(find(ar.begin(),ar.end(),a)!=ar.end()){
ar.erase(find(ar.begin(),ar.end(),a));
}
else cout<<"the number to be delted is not in the set!";
}
};
IntSet operator +(const IntSet& a,const IntSet& b){
bool check=0;
for(int i=0;i<a.ar.size();i++)
for(int j=0;j<b.ar.size();j++)
if(a.ar[i]==b.ar[j])check=1;
if(check)cout<<"The num is in the set!"<<endl;
IntSet ans(b);
for(int i=0;i<a.ar.size();i++)
if(find(b.ar.begin(),b.ar.end(),a.ar[i])==b.ar.end())
ans.ar.push_back(a.ar[i]);
return ans;
};
IntSet operator -(const IntSet& a,const IntSet& b){
IntSet ans(a);
for(int i=0;i<b.ar.size();i++)
if(find(ans.ar.begin(),ans.ar.end(),b.ar[i])!=ans.ar.end()){
ans.ar.erase(find(ans.ar.begin(),ans.ar.end(),b.ar[i]));
cout<<"Delete "<<b.ar[i]<<"!"<<endl;
}
return ans;
};
IntSet operator *(const IntSet& a,const IntSet& b){
IntSet ans(a);
for(int i=0;i<a.ar.size();i++)
if(find(b.ar.begin(),b.ar.end(),a.ar[i])==b.ar.end()){
cout<<"Delete "<<a.ar[i]<<"!"<<endl;
ans.ar.erase(find(ans.ar.begin(),ans.ar.end(),a.ar[i]));
}
return ans;
};
void operator -=(IntSet& a,const IntSet& b){
IntSet ans(a);
for(int i=0;i<a.ar.size();i++)
if(find(b.ar.begin(),b.ar.end(),a.ar[i])!=b.ar.end()){
cout<<"Delete "<<a.ar[i]<<"!"<<endl;
ans.ar.erase(find(ans.ar.begin(),ans.ar.end(),a.ar[i]));
}
a=ans;
};
3.5 Date (++运算符的重载)
测试主函数
int main(){
int year1,year2,month1,month2,day1,day2;
cin>>year1>>month1>>day1;
cin>>year2>>month2>>day2;
Date d1(year1,month1,day1);
Date d2(year2,month2,day2);
cout<<(d1-d2)<<endl;
Date d4=d1+5; d4.show();
Date d5=10+d2; d5.show();
Date d6=d1++; d6.show();
Date d7=++d1; d7.show();
Date d8=++++d1; d8.show();
}
要求实现的输出
13038
2021/1/5
1985/5/1
2020/12/31
2021/1/2
2021/1/4
answer
const int run_mon[]={0,31,29,31,30,31,30,31,31,30,31,30,31};
const int mon[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
inline bool run(int year){
if(year%4==0 &&(year%100!=0 || year%400==0)) return true;
return false;
}
class Date{
public:
int ymd;
Date(){};
Date(const Date& temp){ymd=temp.ymd;};
Date(int _y,int _m,int _d){ymd=_y*10000+_m*100+_d;};
Date(int _ymd){ymd=_ymd;};
Date operator + (int inc){//increase
int y=ymd/10000, m=ymd/100%100, d=ymd%100;
while(inc--){
++d;
if(run(y)){
if(d>run_mon[m]){d=1; m++;};
if(m>12){m=1,y++;};
}
else {
if(d>mon[m]){d=1; m++;};
if(m>12){m=1, y++;};
}
}
return (Date) (y*10000+m*100+d);
}
Date operator ++ (int){//后置++
Date temp=*this;
*this=*this+1;
return temp;
}
Date operator ++ (){//前置++
*this=*this+1;
return *this;
}
void show(){ cout<<ymd/10000<<'/'<<ymd/100%100<<'/'<<ymd%100<<endl; }
};
Date operator + (int inc,Date d1){ return d1+inc; }
int operator - (Date temp1,Date temp2){
int cnt=0;
if(temp1.ymd>temp2.ymd){
while(temp1.ymd!=temp2.ymd)cnt++,temp2++;
}
else{
while(temp2.ymd!=temp1.ymd)cnt--,temp1++;
}
return cnt;
}
3.6 String
class 1
#include <bits/stdc++.h>
using namespace std;
class String {
char *str1,*str2,*str;
String str(char *s1,char *s2){
char *p=str;
while(*s1!='\0')*p=s1++;
while(*s2!='\0')*str=s2++;
*str='\0';
}
void dele(){
char *p1=str,*p2=str;
while(*p1!='\0'){
if(*p1!=' '){*p2=*p1; p2++; }
p1++;
}
}
void sort{
char *l=str,*r=str;
while(*r!='\0'){r++};r--;
for(char *i=l;*i!=r-1;i++)
for(char *j=i+1;*j!=r;j++)
if(*i>*j){ char temp; temp=*i; *i=*j; *j=temp; }
}
void show{
char *p=str;
while(*p!='\0'){cout<<*p; p++; }
}
}
class 2
测试主函数
int main(){
String str1;
str1.set("I love ");
String str2("you");
String str3 = str1+str2;
str3.show();
String str4=str1+"love ";
str4.show();
if(str3<str2) cout<<"str3<str2"<<endl;
else if(str3==str2) cout<<"str3==str2"<<endl;
else cout<<"str3>str2"<<endl;
str1[1] = str2[1];
str1.show();
str2.show();
}
要求实现输出
I love you
I love love
str3<str2
Iolove
you
answer
#include <bits/stdc++.h>
using namespace std;
class String {
public:
string s;
String(){};
String(string _s):s(_s){};
void set(string _s){ s=_s; };
void show(){cout<<s<<endl;}
// 注意这里的char& 如果写成char则不行
char& operator [](int index){ return s[index]; }
};
String operator +(String tem1,String tem2){ return (String)(tem1.s+tem2.s); };
String operator +(String tem1,string _s){ return (String)(tem1.s+_s); };
bool operator <(String tem1,String tem2){ return tem1.s<tem2.s; };
bool operator ==(String tem1,String tem2){ return tem1.s==tem2.s; };
4.友元函数与友元类
4.1友元函数
有时候我们希望某个函数能访问一个类的非公有成员,但又不想把它做成这个类的成员函数,这个时候就可以使用友元。
如果要将一个函数变成一个类的友元,只需要在类中函数前加一个 friend 关键字来声明函数即可,并且访问性不受限制。即表现形式为:
friend <返回类型> <函数名> (<参数列表>);
但这个友元函数他不属于该类的成员函数,他是定义在类外的普通函数,只是在类中声明该函数可以直接访问类中的 private 或者 protected 成员。
class Test{
private:
int a;
protected:
int b;
public:
friend void fun(Test t);// 友元函数
};
void fun(Test t){
t.a=100;
t.b=2000;
cout<<"a = "<<t.a<<", b = "<<t.b<<endl;
}
int main(){
Test test;
fun(test);
return 0;
}
4.2友元类
C++ 中也允许声明一个类为某个类的友元类,方法和声明友元函数旗鼓相当。但是需要注意的是,作为友元的类的声明必须在友元类的声明之前。
class TestFriend{
private:
int a;
};// TestFriend 类的声明在 Test 类之前
class Test{
private:
int a;
friend class TestFriend; // 声明友元类
};
有时候作为友元的类的声明不便放在友元声明之前,这个时候就可以使用前置声明。不过前置声明的类只是一个名字(或者说不完全类型),不能访问它内部的内容。
class TestFriend;// 前置声明 TestFriend 类,只是一个名字
class Test{
private:
int a;
friend class TestFriend; // 声明友元类
// 尝试将 TestFriend 类的成员函数 Func 作为友元函数,
但由于 TestFriend 类目前只有前置声明,所以会出错。
friend void TestFriend::Func();
};
class TestFriend{//TestFriend 类的声明在 Test 类之后
private:
int a;
public:
void Func();
};
由于类型转换时需要访问a种private的变量,所以要在a中将b声明为友元类
#include <iostream>
#include <string>
using namespace std;
class Teacher;
class Student{
private:
int number;
string name,sex;
public:
Student(int num,string nam,string se):number(num),name(nam),sex(se){};
void Print(){
cout<<"学生:"<<name<<",编号:"<<number<<",性别:"<<sex<<endl;
}
friend class Teacher;
};
class Teacher{
private:
int number;
string name,sex;
public:
void Print(){
cout<<"教师:"<<name<<",编号:"<<number<<",性别:"<<sex<<endl;
}
Teacher(const Student &a):number(a.number),name(a.name),sex(a.sex){};
};
4.3应用(矩阵)
#include<bits/stdc++.h>
using namespace std;
class Matrix{
public:
int a[100][100];
int r,c;
Matrix(int _r,int _c):r(_r),c(_c){};
void Fill(int value){
for(int i=0;i<r;i++)
for(int j=0;j<c;j++)
a[i][j]=value;
}
void Set(int r,int c,int value){ a[r][c]=value; }
int Get(int r,int c){ return a[r][c]; }
void Print(){
for(int i=0;i<r;i++)
for(int j=0;j<c;j++)
cout<<a[i][j]<<" ";
cout<<endl;
}
};
Matrix operator + (Matrix &m1,Matrix &m2){
Matrix ans(m1.r,m1.c);
ans.Fill(0);
for(int i=0;i<m1.r;i++)
for(int j=0;j<m1.c;j++)
ans.a[i][j]=m1.a[i][j]+m2.a[i][j];
return ans;
}
Matrix operator - (Matrix &m1,Matrix &m2){
Matrix ans(m1.r,m1.c);
ans.Fill(0);
for(int i=0;i<m1.r;i++)
for(int j=0;j<m1.c;j++)
ans.a[i][j]=m1.a[i][j]-m2.a[i][j];
return ans;
}
Matrix operator * (Matrix &m1,Matrix &m2){
Matrix ans(m1.r,m2.c);
ans.Fill(0);
for(int i=0;i<m1.r;i++)
for(int j=0;j<m2.c;j++)
for(int k=0;k<m1.c;k++)
ans.a[i][j]+=m1.a[i][k]*m2.a[k][j];
return ans;
}
测试主函数
#include "usr.h"
int main(){
int i,j;
cin >> i >> j;
Matrix m1(i,j),m2(i,j),m3(j,i);
m1.Fill(1);
m2.Fill(2);
m3.Fill(0);
for(int s = 0 ; s < i ; s++)
for(int c = 0 ; c < j ; c++)
if(s==c) m3.Set(s,c,s+1);
cout << "m1 + m2 :" << endl ;
(m1 + m2).Print();
cout << "m1 - m2 :" << endl ;
(m1 - m2).Print();
cout << "m1 * m3 :" << endl ;
(m1 * m3).Print();
}