0%

C++语法笔记

c++面向对象

面向对象程序的四个特点:封装、继承、多态、抽象

对象的两个要素:属性行为

类是对象的抽象,对象是类的实例

多态性 是指:由继承而产生的不同的派生类,其对对象的同一消息会做出不同的响应

转换构造函数 的作用是将一个其它类型的数据转换成一个类的对象

类型转换函数 的作用是将一个类的对象转换成另一类型的数据,在函数名面前不能指定函数类型,函数没有参数

虚基类 在继承间接共同基类时只保留一份成员,虚基类不是声明基类时声明的,而是在声明派生类时,指定继承方式时声明的

类和对象

静态成员

目的: 突破不同类对象中的数据共享,类似全局变量

  • 静态数据成员

    • 关键字static加在数据类型之前
    • 只能在 类外数据类型 类名 :: 静态成员函数名 = 初值的形式进行初始化
    • static 数据成员不可以做成构造函数
  • 静态成员函数

    • 主要用来访问静态成员函数,(如下例)访问非静态成员时用“.”运算符

    • 没有this指针,若要使用对象成员必须写入参数

      1
      2
      3
      4
      static Test (ObjName& Object)
      {
      Object.ObjMember;
      }

友元

  1. 类外普通函数 作为 友元函数
    • 在类内声明类外函数是友元函数,声明前加friend
    • 实现在类外调用类内private类型的数据成员
  2. (另一个类的)成员函数 作为 友元函数
    • 在一个类的成员函数中声明另一个类成员函数为友元
    • 有时需要提前声明类,class ClassName;

*常对象(const)和常引用

  1. 常数据成员

    const int test;即定义了一个int类型的数据成员

    • 构造函数只能用初始
    • 化列表对常成员函数进行初始化
  2. 常成员函数

    在成员函数的结尾加上一个const

    • 可以调用常数据成员,常对象 和 普通数据成员

    • 不能改变任何一个被调用数据的值

  3. 常对象和常指针

    • 类名 * const 指针名指针指向的对象不能改变,但对象值可以改变
    • const 类名 * 指针名指针指向的对象可以改变(也可以指向非const类),但对象值不能改变
    • 如果一个变量被声明成了常变量,只能用const在前的那一种指针
  4. 对象的常应引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//  对象的引用
class Time
{
public:
Time(int h,int m,int s):hour(h),minute(m),sec(s){}
int hour;
int minute;
int sec;
};
void fun(time &t)
{t.hour = 18;}
int main()
{
Time t1(10,13,56);
fun (t1);
cout << t1.hour << endl;
return 0;
}
  • 不想改变t1的值可以用void fun(const Time & t)

重载运算符

重载运算符格式(只能作为成员函数)

1
2
3
4
函数类型 operator 运算符名称(形参表)
{
运算符的重载处理
}

不能重载的运算符只有五个”.”*”::”sizeof””?:”

重载流运算符

  • 只能将流运算符作为友元

    1
    2
    3
    4
    5
    6
    //写在类外,并且在类中的public作为友元函数
    ostream & operator <<(ostream & output ,Complex & c)//引用只是个别名
    {
    output << c.real << "+" << c.imag<<endl;
    return output;
    }

类型转换函数

  • 只能作为成员函数
1
2
operator 类型名()
{实现转换的语句}

example:

一个整数和一个复数直接相加,设已有复数类Complex,类中有private有real和imag两个数据成员表示实部和虚部

1
2
3
//写在类Complex中的public作为成员函数
operator int()
{return real;}

这样主函数就可以实现:

1
2
3
4
5
6
int  main()
{
Complex d,d1;
int a=2;
d1 = d + 2;
}

构造函数和析构函数

 1. 用构造函数实现数据成员的初始化
  • 构造函数没有返回值类型,函数名和类名相同

  • 构造函数可以重载,既可以使用不同的函数参数进行对象的初始化

  • 构造函数由编译器自动调用语句,用于对象数据成员的初始化(不需要也不能手动调用)


  1. 默认构造函数
  • 使用默认构造函数的时候使用 Classname obj

  1. 构造函数参数表,类外定义
  • 使用参数表定义构造函数
  • 用参数表对数据成员进行初始化
1
2
3
4
5
6
7
8
9
Box
{
public:
Box (int h,int w,int l):height (h),weight (w),len (l){}//用参数表对数据成员进行初始化
private:
int height ;
int weight ;
int len;
} ;//分号记得加
  • 可以有多个构造函数,构造函数允许缺省

  1. 析构函数
  • 析构函数在类名前加一个~
  • 在类里面只能定义一个析构函数
  • 没有参数

例如~ box( ); 定义在公有类中,析构函数在对象生命周期结束时自动调用,释放内存空间

继承与派生

  • 继承:为了提高程序的可重用性。在一个类的基础上建立一个新的类。被继承的类被称为基类(base class),新建立的类称为派生类(derived class)

  • one base class —> one derived class 单继承(single inheritance);

  • one base class —> some derived class多重继承(multiple inheritance);

  • 形式

    1
    2
    3
    4
    class 派生类名 :[继承方式] 基类名
    {
    派生类新增成员
    };

    继承方式:public , private , protected .

  • 基类成员在派生类中的访问属性

    在基类中的访问属性 继承方式 在派生类中的访问属性
    private private/public/protected 均不可访问
    public private/public/protected private/public /protected(取权限小)
    protected public protected(取权限小)
    protected private private(取权限小)
    protected protected protected(取权限小)
  • 派生类的构成

    1. 从基类接受成员(全部成员,不包括析构和构造)
    2. 调整从基类接受的成员(调整访问属性)
    3. 声明派生类的增加成员
  • 四种访问属性

    1. public类内类外都可以访问
    2. private类内可以访问类外不可以
    3. protected同private,且在下一层的派生中可以访问
    4. 不可访问 类内类外都不可访问
  • 派生类的构造函数

    1
    2
    派生类的构造函数名(总参数表): 基类构造函数名(参数表)//函数调用,实参
    {派生类中新增的数据成员初始化语句}
  • 含有子对象的构造函数

    1
    2
    派生类的构造函数名(总参数表): 基类构造函数名(参数表),子对象(参数表)//函数调用,实参
    {派生类中新增的数据成员初始化语句}
  • 多级派生构造函数

多级派生构造函数只需调用直接基类即可。

  • 多重继承

    1
    2
    3
    派生类的构造函数名(总参数表): 基类1构造函数名(参数表),基类2构造函数名(参数表)...
    //函数调用,实参
    {派生类中新增的数据成员初始化语句}
    • 多重继承的二义性
    1. 两个基类有同名成员(用类名+作用域拓展符(::)解决)
    2. 两个基类和派生类三者都有同名成员(同名覆盖,仅派生类中的起作用)
    3. class A,class B是同一个基类派生(虚基类)
  • 虚基类的初始化(构造函数)

    间接派生类在构造函数中也要写出?

  • 基类和派生类的转换

    1. 派生类对象可以给基类对象赋值
    2. 派生类对象可以替代基类对象向基类对象进行赋值或者初始化

虚基类(解决多重继承二义性问题)

1
2
3
4
5
6
7
8
9
10
11
12
class A
{

};
class B:virtual A
{

};
class C:virtual A
{

};

在派生的类中加入上一个类的虚基类继承(virtual),则仅需要在派生类中添加自己的数据成员;

虚函数

多态性

  1. 静态多态由函数重载来实现

  2. 虚函数的作用:可以输出基类和派生类中的内容不同的同名函数。(动态多态)

example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class student 
{
protected:
int num;
string name;
float score;
public:
student (int n,string na,float s):num(n),name(na),score(s){}
void display()
{
cout << num<<name<<score;
}
};
class graduate :public stduent
{
private:
int wage;
public:
graduate (int n,stirng na,float s,int w):student(n,na,s),wage(w){}
void display() //virtual void display()
{
cout << num<<name<<score<<wage;
}
}
int main()
{
//student obj define
//graduate obj define
student *pt = &student obj;
pt->display();
pt = & granduate obj;
pt ->dispaly();
}
/*
如果不将上一处的注释处改成注释内容;
两个display()均只能输出“name”“score”“num”三个信息
若加上改成注释内容;
main函数中的第一个display()输出三个信息
第二个(指向guaduate的)display将输出四个信息
*/

纯虚函数

纯虚函数一般用于定义抽象类,比如shape类型,派生出circle,rectangle,triangle。

1
2
virtual 函数类型 函数名() = 0;
//"= 0 "仅仅是标志性的,并不是值等于0,告知系统是一个纯虚函数