C++面向对象的编程基础

什么是面向对象的编程

面向对象的编程就是面向具有同一种属性的事物

这里有两种提取方法:一是从上到下的分类。提取的过程就是将事物的共有属性拿出来放到一起,进而形成一个特有的抽象指代名词,而暂时忽略每个事物的个性。而当个性被派上用场是,再从底层相同性中派生出个性。这就是派生类的由来。

面向对象的基本内容

程序运行期的基本实体——对象   

对象就是在类之下的 它拥有抽象名词的共有属性加上自己的个性

实现面向对象的变成的必要条件——类

类就是具体对象所属的一个派别名称

类拥有自己的成员变量和成员函数,它是一些事物相同特性的体现者

类声明一般形式  class 类名

class Dog     定义一个名为Dog的类

{

};

Dog doudou;   声明Dog类的一个对象

实现程序的模块化——封装

封装就是将大程序分成几个实现不同功能的小模块,实际应用中又有对类的封装和对函数的封装。

封装就像是黑盒子,黑盒子就叫函数体,通风口叫参数接口,这是对于函数的封装

下面介绍以下对类的封装

因为类中既有变量成员又有函数,所以它的接口比函数要多

实现系统的可重用及可扩充性——继承

继承能够使原有属性被反复利用,从而能够减少代码的书写量使代码更有逻辑性

同意消息为不同对象接受时产生不同的行为——多态

多态的运行涉及到了virtual和重写这两个概念,多个对象都是由同一个基类派生来的,这就是多态

对象之间沟通的途径——消息传递  

  讨论类的结构和编写规则

类的创建:最基本的方法就是看是否有构造和析构这样的成员函数

C++中类的成员变量分为三类:公有、私有、保护

公有成员  public  在其生命周期内,在任何地方都可以被访问

私有成员  private 只能被该类的其他成员访问,外部函数甚至他的子类就不能进行访问

保护成员  protected 与私有成员一样,但是它可以被其子类访问

 

构造函数

创建规则

构造函数的名字必须和本类的类名一样

构造函数不可以有任何类型的返回值,即使是void也不行

一个类的构造函数可以被重载,即可以由多个构造函数

构造函数定义体  类名::类名()

实现功能:给被建立的对象进行初始化,所以如果一个类没有构造函数,系统就会自动给类生成默认的构造函数,但是该构造函数只会执行创建对象的操作,不会给对象执行任何初始化工作。

何时被调用

 

#include"stdafx.h"
#include <iostream>
using namespace std;
class Baby
{
public:
    Baby();
    ~Baby();
};
class Family
{
public:
    Family();
    ~Family();
private:
    Baby bb;
};

Family::Family()
{
    cout << "Family构造函数被调用" << endl;
}

Family::~Family()
{
}


Baby::Baby()
{
    cout << "Baby构造函数被调用" << endl;
}
Baby::~Baby()
{
}
int main()
{
    Family family;
    return 0;
}
调运顺序

 

 

 默认参数的构造函数

默认构造函数和默认参数的构造函数不是一回事

#include "stdafx.h"
#include <iostream>
using namespace std;

class Adult
{
public:
    Adult(int x = 1,int y = 1);
    ~Adult();

private:
    int X;
    int Y;
};

Adult::Adult(int x, int y)
{
    X = x;
    Y = y;
    cout << "(" << X << "," << Y << ")"<<endl;
}

Adult::~Adult()
{
}



int main()
{
    Adult adult1;
    Adult adult2(20);
    Adult adult3(10, 20);
    return 0;
}
默认参数的构造函数

通过上面的代码可以看出,如果对象没有初始值就使用默认值;如果只给一个初始值则第二个参数值不变,第一个参数用被提供的值,如果给两个初始值,就用初始值。

默认构造函数和默认参数的构造函数不能同时存在,因为如果两个同时存在的话,一旦程序编译,语句不知道该调用哪个构造函数

 

析构函数

当对象要被销毁的时就会调用类的析构函数

创建规则:

同构造函数一样无返回值,也无参数。

函数是在构造函数名之前加一个"~"运算符

不可以被重载,读者可以在析构函数体中自行写释放资源的语句也可不写

执行功能:当一个类的对象被构造函数初始化,计算机会分配给它一部分资源。就像纸张,类对象也是如此,当对象的生命终点的时候就需要被销毁,它在被销毁之前就需要释放在运行过程中所占的资源。从而回到初始状态,这就是析构函数。

何时调用

如果类中没有析构函数,系统会自动为对象加载一个默认的析构函数

就是调用顺序  

1.无其他类对象

析构函数总是在构造函数之后被调用

2.有其他类对象

初始化对象的时候,先调用被调用类的构造函数,再调用主类的构造函数,而释放资源时先释放主类的,再释放被调用类的。

实例:介绍重载构造函数和复制构造函数

重载构造函数

构造函数不同于析构函数

 

 1 class Baby
 2 {
 3 public:
 4         Baby()            
 5         Baby(int age);    重载构造函数
 6         ~Baby();    析构函数
 7 private:
 8         int baby_age;    成员变量
 9 };
10 Baby bb1;    调用默认构造函数    
11 Baby bb2(1);   调用带参构造函数      
重载构造函数

 

复制构造函数

结构体中可以直接将name1的值赋给name2

在C++中对于相同类定义的不同对象,可以用一个对象去构造另一个对象。此时被赋值的另一个对象调用的构造函数就被称为复制构造函数。

 

#include "stdafx.h"
#include <iostream>
using namespace std;

class Adult
{
public:
    Adult(){}
    Adult(int z) {Z = z; }
    void display() { cout << Z << endl; }

    ~Adult(){}
private:
    int Z;
};

int main()
{
    Adult adult1(1);
    Adult adult2;
    adult2 = adult1;
    adult1.display();
    adult2.display();
    return 0;
}
复制构造函数

 

虚函数

功能作用:虚函数就是为实现多态而准备的一种类型函数,还要在其子类中对这个虚函数重新定义,就是基类中的函数被“虚”之后,就可以在子类中进行重写啦。另外从基类派生的子类可以实现多态,但从子类中又派生出的子类也可以形成多态。

具体书写功能

 1 #include "stdafx.h"
 2 #include<iostream>
 3 using namespace std;
 4 
 5 
 6 class Human
 7 {
 8 public:
 9     virtual void Move() { cout << "人类的移动方式" << endl; }
10 };
11 
12 class Person_jia : public Human
13 {
14 public:
15     /**virtual*/ void Move() { cout << "路人甲采用步行移动"<<endl; }
16 
17 };
18 
19 class Person_yi : public Human
20 {
21 public:
22     /**virtual*/ void Move() { cout << "路人乙采用乘公交移动"<<endl; }
23 
24 };
25 
26 class Num1_bus : public Person_yi
27 {
28 public:
29     /**virtual*/ void Move() { cout << "路人乙采用乘916路公交移动"<<endl; }
30 
31 };
32 
33 class Num2_bus : public Person_yi
34 {
35 public:
36     /**virtual*/ void Move() { cout << "路人乙采用乘12路公交移动"<<endl; }
37 
38 };
39 
40 class Person_bing : public Human
41 {
42 public:
43     /**virtual*/ void Move() { cout << "路人丙采用开QQ车移动"<<endl; }
44 
45 };
46 
47 int main()
48 {
49     Person_jia  fangshi1;
50     Person_yi   fangshi2;
51     Num1_bus    fangshi3;
52     Num2_bus    fangshi4;
53     Person_bing fangshi5;
54 
55     Human *human[5] = { &fangshi1,&fangshi2,&fangshi3,&fangshi4,&fangshi5 };
56 
57     for (int i = 0; i < 5; i++)
58     {
59         human[i]->Move();
60     }
61 
62 
63     return 0;
64 }
虚函数应用实例

 详解派生类

派生类就是从基类中继承而来的类,所有的类都可以派生出一个新类,原先的类被叫做基类或父类。新类被叫做派生类或者子类。

派生类从何派生而来

派生类是单一继承而来

派生类是多重继承而来的  那它就可以拥有多个基类的性质

如何书写  多重继承:class 派生类名 : 继承方式 基类名1,继承方式 基类名2,...,继承方式,基类名n

#include "stdafx.h"
#include<iostream>
using namespace std;

class Image
{
public:
    Image() { cout << "Image construct" << endl; }
    ~Image()
    {
        cout << "Image deconstuct" << endl;
    }
};

class Bmp : public Image
{
public:
    Bmp() { cout << "Bmp construct" << endl; }
    ~Bmp() { cout << "Bmp deconstruct" << endl; }
};




int main()
{
    Bmp bmp;
    return 0;
}
单一继承

多重继承就是在继承方式基类名后 加上多个继承方式和基类名就可以了

友元

C++友元的出现是因为封装,外部变量不可以访问私有成员。就是封装的整体对友元开放

C++描述友元的关键字是friend友元可以是一个函数也可以是一个类

class Arithmetic
{
public:
    Arithmetic(int_a = 0, int_b = 0);
    void show();
    friend Arithmetic add(Arithmetic &arith);
    friend int sub (Arithmetic &arith);

private:
    int a, b;
};
友元函数的应用
class Ada_Arithmetic
{
public:
    Ada_Arithmetic();
    ~Ada_Arithmetic();
    friend class Arithmetic;
private:
    int x,y;
};
应用友元类

重载

重载就是对现有事物进行另一种方式的描述

函数的重载

函数的名字必须一模一样

在函数参数个数相同条件下,参数的类型必须不同

在函数的参数类型相同的条件下,参数的个数必须不同

以上三种条件满足情况下,函数的返回类型值可相同也可不同

重载和重写的不同

重写:因为应用于多态的实现,所以只能在被派生类中。另外被重写的函数必须跟基类的函数一模一样,不管是“返回值类型”、“函数名”、“参数列表”

功能作用

重写:针对不同对象实现相同功能

重载:针对不同对象实现不同功能

#include "stdafx.h"
#include<iostream>
using namespace std;

double Distance(int array1[2], int array2[2])
{
    double distance = 0;
    distance = sqrt((float)((array1[0] - array2[0]) * (array1[0] - array2[1])) + (array1[1] - array2[1]) * (array1[1] - array2[1]));
    return distance;
}

double Distance(float array1[2], float array2[2])
{
    double distance = 0;
    distance = sqrt((float)((array1[0] - array2[0]) * (array1[0] - array2[1])) + (array1[1] - array2[1]) * (array1[1] - array2[1]));
    return distance;
}

int main()
{
    int a[2] = { 1,1 };
    int b[2] = { 3,3 };
    cout << "整型点{1,1}和{3,3}间的距离为:" << Distance(a, b) << endl;

    float c[2] = { 1.0,1.0 };
    float d[2] = { 0.0,1.0 };
    cout << "浮点型点{1.0,1.0}和{0.0,1.0}间距离为:" << Distance(c, d) << endl;
    return 0;
}
函数应用重载实例

运算符的重载就是对运算符的重新定义即可

实例:具体实现封装、继承

 

posted @ 2018-03-24 19:24  为我所爱一路奋战  阅读(57)  评论(0)    收藏  举报