C++总结
构造函数以及基础
- 关于三种构造函数
//下边的三个函数实现了函数重载
//类的带参构造函数(没有默认值) 只有它时会把无参构造覆盖
Coordinate(int x1, int y1){x=x1; y=y1;}
//带有一个默认参数的构造函数 必须从右到左赋给默认值
Coordinate(int x1,int y1=5){}
//调用下边函数 会把2赋值给x1的位置
Coordinate p5(2);
//带有2个参数的默认值 这个函数相当于写了3个函数 无参构造,带有一个参的构造,带有2个参的构造
Coordinate(int x1=2,int y1=5){}
//初始化成员列表 带有默认值这里不需要无参构造
A(int _a1=0,int _a2=0,int _a3=3):a1(_a1),a2(_a2),a3(_a3){ };
//类中的拷贝构造函数,不定义有默认的 参数为该类的有一个对象的引用 (当对象要做参数传入时一般传引用)
Coordinate(Coordinate &p){};
//创建一个该类对象
Coordinate p1(2,3);
//拷贝函数的调用 不会在调用普通构造函数
Coordinate p2(p1)
Coordinate p3=p2;
//析构函数,最后在用完对象,对象要消失时会执行,可以用于删除数据成员为指针的变量 delete name;(这里name被char *name定义过)
~Coordinate(){
cout<<"Destructor is called."<<endl;
}
//类外写某类的成员函数(这里在类外定义拷贝构造函数) 前提是Coordinate(Coordinate &p);已经在类中声明
(返回值) 类名::方法名(){}
Coordinate::Coordinate(Coordinate &p){
x=p.x;
y=p.y;
}
//键盘录入信息时,定义输入函数直接输入信息到数据成员中,不要在方法中调用构造函数
void input(){
cin>>name;
cin>>num;
cin>>chinese;
cin>>math;
cin>>english;
}
- 使用指针创建对象以及调用方法,友元函数
//定义一个该类的指针,为它用new分配空间
Timer *pt=new Timer(12,59,59)
//指针对应的对象调用方法通过指针要使用箭头调用
pt->printUniversal();
pt->printStandard();
delete pt;
//友元函数
//一个全局函数在一个类中声明为friend 方法,则该全局函数称为该类的友元函数,此时该全局函数可以访问该类的私有成员
class location{
private:
double x,y;
public:
location(double _x=0,double _y=0):x(_x),y(_y){
}
//友元函数
friend double distance1(location &l1,location &l2);
};
double distance1(location &l1,location &l2){
return sqrt(pow(l1.x-l2.x,2)+pow(l2.y-l1.y,2)) ;
}
- 数组对象,指针变量做数据成员
#include<iostream>
#include<cstring>
using namespace std;
class Employee{
private:
long id;
//这里只是定义了指针变量,其中*代表是指针类型的,name代表变量,所以方法中使用name即可,不使用*name
//但是没有分配空间,在构造函数中分配空间
char *name;
//char name[20] 这样name就提前分配好了空间
char *address;
double salary;
public:
//构造函数
Employee(long _id,char *_name,char *_addr,double d){
id=_id;
salary=d;
//给指针变量的数据成员分配空间根据内容大小 +1是因为还有/0结束符
name=new char[strlen(_name)+1];
//把内容放到name指针变量指向的空间
strcpy(name,_name);
address=new char[strlen(_addr)+1];
strcpy(address,_addr);
}
//析构函数
~Employee(){
delete name;
delete address;
}
void set_id(long _id){
id=_id;
}
void set_salary(double s){
salary=s;
}
//这里加char是为了确保_name变量保存的内容不发生改变,只是用于赋值
void set_name(const char *_name){
name=new char[strlen(_name)+1];
strcpy(name,_name);
}
void set_address(const char *_addr){
address=new char[strlen(_addr)+1];
strcpy(address,_addr);
}
long get_id(){
return id;
}
double get_salary(){
return salary;
}
char* get_name(){
//这里返回的是name指针变量里边的内容
return name;
}
char* get_address(){
return address;
}
void print(){
//这里打印的是name指针变量里边的内容
cout<<"name:"<<name<<" id:"<<id <<" address:"<<address<<" salary:"<<salary<<endl;
}
};
int main(){
//定义数组对象传参
char name[20]="hj";
char address[20]="";
Employee e1(123,name,address,3000);
cout<<e1.get_name()<<" "<<e1.get_id()<<" "<<e1.get_address()<<" "<<e1.get_salary()<<endl;
e1.set_address("China");
e1.set_id(2344);
e1.set_salary(4000);
e1.set_name("hys");
e1.print();
}
静态成员变量和方法
-
静态成员变量初始化赋值在类外,定义静态成员变量在类里 ,静态成员方法定义可以在类里边
-
静态成员函数只能访问静态成员变量或静态成员函数,不可访问非静态的普通成员函数、成员变量
#include<iostream>
#include<cstring>
using namespace std;
class Student{
private:
int score;
//定义静态成员在修饰符后,返回值前加static修饰
static int total_score;
static int count;
public:
Student(){
}
Student(int s){
score=s;
}
~Student(){
}
void account(int s){
score=s;
total_score+=s;
count++;
}
void print(){
cout<<"当前学生成绩"<<score<<endl;
}
//静态成员函数只能访问静态成员变量或静态成员函数,不可访问非静态的普通成员函数、成员变量
static int sum(){
return total_score;
}
static int average(){
return total_score/count;
}
};
//静态成员函数初始化在外边 定义静态成员数据使用static在类里
//静态成员变量一定要在类定义对象之前在类的外面进行初始化赋值,不能在类的里面,因为静态变量属于所有对象,
int Student::total_score=0;
int Student::count=0;
int main(){
//定义一个班的学生用数组 这里的每个stu是使用无参构造调用的,所以记得加无参构造方法
Student stu[5];
//用于录入数据
int s;
for(int i=0;i<5;i++){
cin>>s;
stu[i].account(s);
stu[i].print();
}
//静态成员函数调用通过类名加::(双冒号)直接调用
cout<<"成绩之和:"<<Student::sum()<<" 平均分:"<< Student::average()<<endl;
}
- 关于魔方一道题
//定义4*4的魔方阵,是指该矩阵的各行值的和等于各列值的和,并等于两对角线值的和
#include<iostream>
using namespace std;
class magic{
private:
int first,step;
int m[4][4];
public:
//键盘录入初始值
void getdata(int _f,int _s){
first=_f;
step=_s;
}
void setfirstmagic(){
//将数据输入魔方
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
cout<<"m["<<i<<"]["<<j<<"]:";
cin>>m[i][j];
}
}
}
//生成最终魔方成员函数 这里返回值int为题中要求可以return 0
int generate(){
//用32减去初始魔方阵所有对角线(两条)上元素的值,然后将结果放在原来的位置
int sum=m[0][0]+m[3][3];
for(int i=0;i<4;i++){
m[i][i]=sum-m[i][i];
m[i][3-i]=sum- m[i][3-i];
}
return 0;
}
//输出魔方
int printmagic(){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
cout<<m[i][j]<<"\t";
}
cout<<"\n";
}
return 0;
}
}
;
int main(){
magic m;
m.getdata(1,2);
m.setfirstmagic();
m.generate();
m.printmagic();
}
派生
- 点派生圆类
- 在建立继承类的构造函数时,初始化被继承类的数据成员时用其构造函数
- 继承后子类可以使用父类的public方法
#include<iostream>
#define PI 3.14159
using namespace std;
class Point{
private:
int x,y;
public:
Point(int a=0,int b=0){
x=a;
y=b;
}
void ShowPoint(){
cout<<"Point:("<<x<<","<<y<<")\n";
}
int Getx(){
return x;
}
int Gety(){
return y;
}
void setxy(int a,int b){
x=a;
y=b;
}
};
//定义圆类 公有继承点类
class Circle:public Point{
private:
int r;
public:
//初始化时被继承类的数据成员初始化使用其构造函数
Circle(int x,int y,int ra):Point(x,y),r(ra){
}
void setr(int ra){
r=ra;
}
double Aera(){
return PI*r*r;
}
void Move(int x_offset,int y_offset){
int x1=Getx();
int y1=Gety();
x1+= x_offset;
y1+= y_offset;
setxy(x1,y1);
//这里不能使用x/y,因为x/y在父类中为私有属性,将private修改为protected
//数据成员的修饰符将取决于该类怎么继承父类,这里公有继承,当修改后可以使用x/y
// x=x+x_offset;
// y=y+y_offset;
// setxy(x,y);
}
void showCircle(){
ShowPoint();
cout<<"Radius:"<<r<<"\t";
cout<<"Aera:"<<Aera()<<endl;
}
};
int main(){
Circle c(1,1,1);
c.showCircle();
c.Move(1,2);
c.showCircle();
//通过子类创建的对象可以直接访问父类方法
c.setxy(4,5);
c.setr(2);
c.showCircle();
}
- 派生类中方法重写的使用
//重写输入教师资料方法
void getdata(){
//表示调用其父类employer的getdata()方法
employer::getdata();
cout<<"输入工作时间"<<endl;
cin>>hour;
}
运算符重载的方法
-
单目运算符只有一个操作数
-
双目运算符:两个操作数
-
使用operator关键字
友元函数的自增(两种)
#include<iostream>
using namespace std;
class point {
private:
int x,y;
public:
point(int _x=0,int _y=0):x(_x),y(_y){
}
//重载前置++ 返回一个点类 定义友元为了全局函数可以访问x,y私有成员变量
friend point& operator++(point &p);
//重载后置++ 返回一个点类 int是为了函数重载
friend point operator++(point &p,int);
void print(){
cout<<"("<<x<<","<<y<<")"<<endl;
}
};
//前置++ 先++后赋值 &表示返回加后的自己,而不会调用拷贝构造函数
point& operator++(point &p){
p.x++;
p.y++;
return p;
}
//后置++ 先赋值后++
point operator++ (point &p,int){
point t=p;
p.x++;
p.y++;
return t;
}
int main(){
point p1(1,1);
//后置++ 先赋值 后++
point p2=p1++;
p1.print();//(2,2)
p2.print(); //(1,1)
//前置++ 先++ 后赋值
point p3=++p2;
p3.print();//(2,2)
p2.print(); //(2,2)
}
成员函数的自增(两种)
#include<iostream>
using namespace std;
class Point{
private:
int x,y;
public:
Point(int _x=0,int _y=0):x(_x),y(_y){
}
//前置++
Point& operator++();
//后置++
Point operator++(int);
void print(){
cout<<"("<<x<<","<<y<<")"<<endl;
}
};
//前置++
Point& Point::operator++(){
x++;
y++;
return *this;
}
//后置++
Point Point::operator++(int){
Point p=*this;
x++;
y++;
return p;
}
int main(){
Point p1(1,2);
//前置++
Point p2=++p1;
p1.print();//(2,3)
p2.print(); //(2,3)
//后置++
Point p3=p2++;
p3.print();//(2,3)
p2.print();//(3,4)
}
- .定义一个分数类,通过重载运算符实现分数的四则运算、求负运算和赋值运算。其中,要求加法“+” 和减法“-”用友元函数实现重载,其他运算符用成员函数实现重载。
#include<iostream>
using namespace std;
class FS{
private:
int fz,fm;
public:
FS(int _fz=0,int _fm=1):fz(_fz),fm(_fm){
}
//友元实现+ -重载 这是双目运算符
friend FS operator+(const FS &fs1,const FS &fs2);
friend FS operator-(const FS &fs1,const FS &fs2);
//成员函数*和/
FS operator*(const FS &fs);
FS operator/(const FS &fs);
//求负和赋值运算符 赋值运算符是双目运算符 ,取反为单目
FS& operator-();
FS operator=(const FS &fs);
void print(){
cout<<"计算所得分数为"<<fz<<"/"<<fm<<endl;
}
};
//定义全局最小公倍数用于分母通分
int lcm(int m,int n){
int m1=m,n1=n;
int t;
//比较大小把大的放前边
if(m<n){
t=m;
m=n;
n=t;
}
//辗转相除找最大公约数
while(m%n!=0){
t=m%n;
m=n;
n=t;
}
//求最小公倍数 =两数乘积/最大公约数
return m1*n1/n;
}
//定义一个全局+运算符重载函数
FS operator+(const FS &fs1,const FS &fs2){
FS fs;
//得到最小公倍数
fs.fm=lcm(fs1.fm,fs2.fm);
fs.fz=fs1.fz*fs.fm/fs1.fm+fs2.fz*fs.fm/fs2.fm;
return fs;
}
FS operator-(const FS &fs1,const FS &fs2){
FS fs;
//得到最小公倍数
fs.fm=lcm(fs1.fm,fs2.fm);
fs.fz=fs1.fz*fs.fm/fs1.fm-fs2.fz*fs.fm/fs2.fm;
return fs;
}
FS FS::operator*(const FS &fs){
FS rfs;
rfs.fz= this->fz*fs.fz;
rfs.fm=fs.fm*this->fm;
return rfs;
}
FS FS::operator/(const FS &fs){
FS rfs;
rfs.fz=this->fz*fs.fm;
rfs.fm=this->fm*fs.fz;
return rfs;
}
//该取反运算符把自己也改变了,返回自己所以加&
FS& FS::operator-(){
this->fz=-this->fz;
return *this;
}
FS FS::operator=(const FS &fs){
if(this==&fs){
return *this;
}
this->fz=fs.fz;
this->fm=fs.fm;
return *this;
}
int main(){
FS fs1(2,3);
FS fs2(1,2);
//测试 +
FS fs3=fs2+fs1;
fs3.print();//7/6
//测试 -
FS fs4=fs2-fs1;
fs4.print();//-1/6
//测试 *法
FS fs5=fs1*fs2;
fs5.print();//2/6
//测试 /法
FS fs6=fs1/fs2;
fs6.print();//4/3
FS fs7=-fs1;
fs7.print(); //-2/3
fs1.print();//-2/3
fs6=fs2;
fs6.print();//1/2
}
虚函数
-
定义虚函数 基类函数被定为虚函数 ,则派生类中同名函数都是虚拟函数,不论继承多少层
-
定义为抽象类 (含***有等于0的虚函数的类***即含有纯虚函数的类)
-
虚函数有方法体,纯虚函数为0
-
抽象类不能创建对象
-
让基类指针指向派生类的对象 ,在基类的方法前用virtual修饰,可以在基类指针指向派生类对象时使用派生类的方法
#include<iostream>
using namespace std;
//该类定义为抽象类 (含有等于0的虚函数的类即含有纯虚函数的类)
class vehicle{
//默认修饰符为private 记得写 public
public:
vehicle (){
cout<<"vehicle constructor"<<endl;
}
//非构造函数记得写返回值
//定义虚函数 基类函数被定为虚函数 ,则派生类中同名函数都是虚拟函数,不论继承多少层
//纯虚函数 值为0
virtual void run()=0;
virtual void stop()=0;
//虚函数
virtual void run(){
cout<<"run"<<endl;
}
};
class bicycle: virtual public vehicle {
public:
bicycle(){
cout<<"bicycle constructor"<<endl;
}
void run(){
cout<<"bicycle run"<<endl;
}
void stop(){
cout<<"bicycle stop"<<endl;
}
};
class motorear: virtual public vehicle{
public:
motorear(){
cout<<"motorear constructor"<<endl;
}
void run(){
cout<<"motorear run"<<endl;
}
void stop(){
cout<<"motorear stop"<<endl;
}
};
//写虚拟继承在这里没有什么作用
class motorbicycle: public bicycle, public motorear{
public:
motorbicycle(){
cout<<"motorbicycle constructor"<<endl;
}
void run(){
cout<<"motorbicycle run"<<endl;
}
void stop(){
cout<<"motorbicycle stop"<<endl;
}
};
int main(){
// vehicle类为抽象类不能创建对象
// vehicle v;
// v.run();
// v.stop();
bicycle b;
b.run();
b.stop();
motorear mr;
mr.run();
mr.stop();
motorbicycle mb;
mb.run();
mb.stop();
cout<<"-----------------------------"<<endl;
//定义vehicle指针
vehicle *ve;
// 让基类指针指向派生类的对象 ,在基类的方法前用virtual修饰,可以在基类指针指向派生类对象
//时使用派生类的方法
ve=&b;
ve->run();
ve->stop();
ve=&mr;
ve->run();
ve->stop();
ve=&mb;
ve->run();
ve->stop();
}
抽象类
-
基类函数被定为虚函数 ,则派生类中同名函数都是虚拟函数,不论继承多少层
#include<iostream> #include<cmath> #define PI 3.14159 using namespace std; //定义抽象类 必须有纯虚函数 class Container{ public: //抽象方法 这有纯虚函数在继承该抽象类的类中必须重写抽象方法 virtual double aera()=0; virtual double volume()=0; }; class Sphere: public Container{ private: double radius; public: Sphere(double r=0):radius(r){ } double aera(){ return 4*PI*pow(radius,2); } double volume(){ return 4/3*PI*pow(radius,3); } }; class Cylinder:public Container{ private: double radius,height; public: Cylinder(double r=0,double h=0):radius(r),height(h){ } double aera(){ return PI*2*radius*(height+radius); } double volume(){ return PI*pow(radius,2)*height; } }; int main(){ Sphere s1(10); cout<<"球表面积:"<<s1.aera()<<" 球体积:"<<s1.volume()<<endl; Cylinder c1(10,10); cout<<"圆柱表面积:"<<c1.aera()<<" 圆柱体积:"<<c1.volume()<<endl; }