c++学习指难

class test{
    private:
    默认为private
        
    public:
    
};

#函数

构造函数

  • 系统自动调用的初始化函数

  • 函数名与类名相同

  • 无返回值

  • 公有函数(必须)

  • 可以重载

  • 可以带默认形参

    (一般用于初始化值)

  1. 成员初始化列表

在无const引用类型时,通常使用(this指针)初始化,若存在const和引用类型时,用初始化列表初始化(如下)。

  • 普通成员(无const、static)初始化时可以直接赋值
  • image-20220329211317670
  • 类内常成员必须使用初始化列表进行初始化
class Student{
  private:
      const int ID;
      string name;
      int age;
      const bool gender;
      float *score;
      int scoreLength;
  public:
//无参数构造函数
    Student():ID(2021013274),gender(true)
    {
        this->name="李尧";
        this->age=19;
        this->score=new float [2]{(100),(100)} ;
        this->scoreLength=2;
    }
    
    int main()
    {
        //无参数
        Student a;
        return 0;
    }

//有参数构造函数
Student (const int ID,string name, int age,const bool gender,float *score,int scoreLength):ID(ID),gender(gender)
{
    this->name=name;
    this->age=age;
    this->scoreLength=scoreLength;
     this->score= new float [scoreLength];
    for(int i=0;i<scoreLength;i++)
    {
        this->score[i]=score[i];
    }
}
    
};    
  • 若在带参数后面直接声明参数值,则可少些一种不参的构造函数

      Point2D(float x=0,float y=0)
          {
          this->x=x;
          this->y=y;
          }
    //相当于写了两种构造函数,一种含参,另一种不含参。
    

###析构函数

  • 对象消失时的清理工作

  • 释放单元等

  • 析构函数不能被重载

  • 析构函数不可以带参数

    ~WowID(){
        this->age=0;
        this->name="";
        this->scoreLength=0;
        delete []this->score;
    }
    

数组用delet、 数值归零、string类型变为“”(空)、

拷贝构造函数

  1. 浅拷贝:WowID herID(myID)把myID的值给herID,
  • 上述系统自动生成的拷贝构造函数
  • 缺点:难以应对指针引用参
  1. 深拷贝:需要重载构造函数
//深拷贝构造函数
Student(const Student &copied):ID(copied.ID),gender(copied.gender)
{
 this->name=copied.name;
 this->age=copied.age;
 this->scoreLength=copied.scoreLength;
 this->score= new float[scoreLength];
 for(int i=0;i<scoreLength;i++)
 {
    this->score[i]=copied.score[i];
 }
}
  • 参数为引用类型

成员函数

//求平均score的函数
float py()
{
    float a=0;
    for(int i=0;i<this->scoreLength;i++)
    {
        a=a+this->score[i];
    }
    return a/this->scoreLength;
}

复杂对象

对象指针

  1. 指向对象存放的地址

  2. 类名==*==对象指针名;对象指针名->成员变量名;

    对象指针名->成员函数名;

动态对象

  1. 类名 对象指针名=new 类名(构造参数);
  • 只建立一个对象

  • int *a=new int(120);

申请一个整型变量空间,赋初值为120,并定义一个整型指针a指向该地址空间

  • delete 对象指针名;
  1. 类名 对象指针名=new 类名[n];
  • 建立一组类
  • delete []对象指针名;
  1. 结合1,2
  • Student *stu new Student[2]{{"1"},{"2"}};
    既建立多个对象,又分别初始化
    

对象数组

  1. 以对象为元素的数组

  2. 类名 对象数组名[n];

    • 数组名[n]={类名(构造参数表1), 类名(构造参数表2), … 类名(构造参数表n)};一定要加类名

    • WowID a[5] = {WowID(106067, "部落猪联盟狗", 1),
      WowID(106068, "呀哈哈", 1),
      WowID(106069, "杨凌彭于晏", 0),
      WowID(106070, "黄忠", 1),
      WowID(106071, "战士冲锋", 0)};
      

组合对象

  1. 类中含有其他类的对象作为成员

  2. 初始化:

组合类名(参数表):成员对象1(子参数表1), 成员对象2(子参数表2)

  • 构造函数调用顺序 ,按照组合类的声明中出现的次序 ,与初始化列表无关
class KingAcc{
private:
int ID; string name;
public:
KingAcc;
KingAcc(int id, string name);
};
class KingTeam{       //组合类名
private:
string name; 
KingAcc cap; KingAcc mem;
public:
KingTeam(string name, KingAcc cap,
KingAcc m):mem(m), cap(int id,string name){
this->name = name;
}
};
//例二
class Circle{
  private:
      Point2D center;
      float radius;
      static int Num;
  public:
    const float PI;
    Circle(float x=0,float y=0, float r=0):center(x,y),PI(3.14f)
    {
        this->r=radius;
    }

static和const成员

静态成员

  1. 不同对象数据成员和函数的共享,在内存中只对应一个存储区域。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zo2FGUVg-1651677360648)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220331202543174.png)]

  • 在程序运行开始之前就存在
  • 静态成员函数无this指针
  1. 静态成员函数

​ static 数据类型 静态成员名;

​ static 返回类型 函数名;

  1. 静态成员初始化方法(一般在主函数之前)

​ 数据类型(const) 类名::静态成员名;

int Point2D::number = 0;
static const int e;  //类内声明
const int ReviewConst::e = 5;  //类外
  • 不用再写static

const成员函数

  1. 返回类型 成员函数名(参数表) const

    • 常用于访问器函数,
    • 修改器函数(不能使用const)
    class KingAcc{
    private:
    int ID; string name;
    public:
    int getID() const{
    return this->ID;
    }
    string getName() const{
    return this->name;
    }
    };
    //类外定义时
    string KingAcc::getName() const
    {
    return this->name;
    }
    
    
    • 注意事项
    • 不能更新数据成员
    • 不能调用非常成员函数
    • 定义和声明时都要加const

友元

##友元函数

  1. 在类中声明,在类外定义
    • 可以调用和修改私有成员
friend float Distance(Point2D a,
Point2D b);   
};//类中
float Distance(Point2D a, Point2D b)
{
    //类外定义
}

友元类

• 单向性
• A类被声明为B类的友元
• A类成为B类的友元类
• A类所有成员函数为B的友元函数
>>A可以调用B
• 但B类不能调用A类的私有成员
  class B{
...
friend class A;
};
  

继承与派生

定义及语法

  • 原有类:基类(父类)
  • 新类:派生类(子类)
class 派生类名:继承方式 基类1,继承方式 基类2{
private:
派生类私有成员      
public:
派生类公有成员
protected:
派生类保护成员
};

派生类构造函数
   派生类名(参数表):基类名1(参数表1),基类名n(参数表n)
{
派生类新增成员初始化
}

多层继承时在参数列表应该包含最初的基类

  • 继承方式:

    ​ public:公有继承

    ​ private:私有继承

    ​ proteted:保护继承(未发生继承时和私有类型一样)

继承方式\基类属性publicprotectedprivate
publicpublicprotected不可访问
protectedprotectedprotected不可访问
privateprivateprivate不可访问

类型兼容

定义:

  • 公有派生的情况下,一个派生类对象可作为基类的对象来使用

  • 派生类的对象可以赋值给基类对象

  • 派生类对象可以初始化基类的引用

  • 派生类对象的地址可赋给指向基类的指针

###成员变量、函数覆盖

class A{                    
public:
void Func()
{
    cout<<"A"<<endl;
}
};
class B:public A{ 
public:
void Func()
{
     cout<<"B"<<endl;
}
};
    int main(){
         B b;
         b.Func();
         return 0;
}
输出为B
    
int main()
{
   B b;
   A a1(b);
   A *a2 = &b;
   A &a3(b);
   a1.Func();
   a2->Func();
   a3.Func();
   return 0;
}
输出均为A
    
  
    说明:用子类(B)对象初始化父类(A),但仍是声明时的父类(A),只是用子类赋值父类而已
  • **子类对象可以初始化父类对象 **

  • 父类对象不能初始化子类对象

##多继承

  • 派生类继承多个基类,调用时,按照继承时声明顺序从左向右

二义性问题

  • 派生类的多个基类中拥有同名成员,调用该成员将出现二义性

分类:

  • 间接二义性
  • 直接二义性

解决方法

虚基类:

###定义

  • class 派生类名:virtual 继承方式 基类名,virtual 继承方式 基类名

作用

  • 虚基类构造函数只被调用一次

重载

函数重载

  • 相同功能不同数据类型(或参数个数)
  • 使用同名函数实现

区分依据:

  1. 函数名
  2. 参数类型(非指针和引用上的const无法区分)
  3. 参数个数
  • 返回类型无法区分
double getEarning(double salary, int absenceDays)
{
    double a;
    return a=salary-absenceDays*salary/22;
}
double getEarning(double baseSalary, double salesSum, double rate)
{
    double a;
    return a=baseSalary+salesSum*rate;
}
double getEarning(int workPieces, double wagePerPiece)
{
    double a;
    return a=workPieces*wagePerPiece;
}

运算符重载

  1. 说明:
  • 同一个运算符作用于不同类型数据时
  • 实现功能相近的操作

可重载运算符

image-20220422113136535

不可重载运算符

image-20220422113302837
  1. 重载规则

    • 重载后运算符的优先级和结合性不变
    • 运算符操作数的个数不能改变
    • 不能重载C++中不支持的运算符 如@ # $等
    • 保持运算符的语义
  2. 运算符重载方式

  • 定义:返回类型 operator运算符(形参表)

(1)重载为类的成员函数

  • 可以省略一个形参,另一个参数实际通过this指针隐式传递

eg:

Complex operator=(const Complex& a){
Complex b;
b.real = a.real;
b.imag = a.imag;
b.print();
b.print();
return b;
}
Complex a(1,1);
Complex c(0,0);
c = a;
c.print();
输出1+1i,0+0i
    原因:c=a,调用的是c的成员函数,然后返回出中间参数b,但是没有变量收到中间参量的值,所以c是啥还是啥,相当于
把c=a看成一个整体,运行完c=a,后直接返回中间参量b
若改成c=(e=a)就对了
或者直接变成变量本身   
 Complex operator=(const Complex& a){
this->real = a.real;
this->imag = a.imag;
return *this;(即类本身)
}  
Complex a(1,1);
Complex c(0,0);
c = a;
c.print();

(2)重载为类的友元函数

  • 语法:friend 返回类型 operator 运算符(形参表)[需要给出所有参数];

  • 友元函数没有this指针

  • 若使用==单目运算符且修改数据成员需要使用引用类型==

    eg:friend Complex operator--(Complex &a);

    friend Complex operator--(Complex &a, int x);

    Complex operator*(int x){
    Complex result;
    result.real = x*this->real;
    result.imag = x*this->imag;
    return result;
    }
    friend Complex operator*(int x, Complex &a);
    Complex operator*(int x, Complex &a){
    Complex r(a);
    r.real *= x;
    r.imag *= x;
    return r;
    }
    int main()
    {
        Complex a(1,1);
         a=a*6;
         a=6*a;
         return 0;
    }
    
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bLHehxE5-1651677360650)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220503153426928.png)]

  • 典型运算符重载(<< >>)
friend istream &operator>>(istream &in,Complex &c);
istream &operator>>(istream &in, complex &C)
{
    in>>c.real>>c.imag;
    return in;
}
friend ostream &operator<<(ostream &out,Complex c);
ostream &operator<<(ostream &out,Complex c)
{
    out<<c.real<<"+"<<c.imag<<"i"<<endl;
    return out;
}
int main()
{
    Complex a,b;
    cin>>a>>b;
    cout<<a<<b;
    return 0;
}

image-20220503155020168

运算符函数与返回类型

  1. 如果仅为只读参数的值,应作为==const &==来传递

    Complex operator+(const Complex& a)
    {
       Complex result;
       result.real = a.real + this->real;
       result.imag = a.imag + this->imag;
       return result;
    }
    
  2. 如果产生一个新值,就需要产生一个作为返回值的新对象,这个对象作为一个常量通过传值方式返回

const Complex operator+(const Complex& a)
{
   Complex result;
   result.real = a.real + this->real;
   result.imag = a.imag + this->imag;
   return result;
}
  1. 如果函数返回的是原有对象,通常以引用方式返回,根据是否希望对返回的值进行运算来决定是否返回const &
Complex &operator()(int r, int i)
{
  this->real = r;
  this->imag = i;
  return *this;
}
const Complex &operator()(int r, int i)
{
   this->real = r;
   this->imag = i;
   return *this;
}

lex& a)
{
Complex result;
result.real = a.real + this->real;
result.imag = a.imag + this->imag;
return result;
}


2. 如果==产生一个新值==,就需要产生一个作为返回值的新对象,这个对象作为一个==常量==通过传值方式返回

```c++
const Complex operator+(const Complex& a)
{
Complex result;
result.real = a.real + this->real;
result.imag = a.imag + this->imag;
return result;
}
  1. 如果函数返回的是原有对象,通常以引用方式返回,根据是否希望对返回的值进行运算来决定是否返回const &
Complex &operator()(int r, int i)
{
  this->real = r;
  this->imag = i;
  return *this;
}
const Complex &operator()(int r, int i)
{
   this->real = r;
   this->imag = i;
   return *this;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值