02__C++面向对象

(一)初窥类与对象
1.示例demo
class class_name{    
    int x = 0;

public:
    class_name();
    ~class_name();
    friend void friendfunc(int x);
    int a = 1;
    void func();
    
protcted:
    int b = 2;
private:
    int c = 3;

};
void class_name::func(void)
{
    /*...*/
}
实例化:class_name A; or  class_name *class_ptr = new class_name;
从上可以看出一些point:结构、访问权限关键字、成员(属性和方法)、实例化、构造函数与析构函数等。

2.类成员函数
就是定义在类里面的属性和方法;
可以在类定义里面定义,也可以在外部定义,不过一定要指明是那个对象的成员函数,如上func的定义。

3.类访问权限关键字
public、protected、private
使用时如上加:

尤其注意:
(1)类成员都有访问权限,若没有加关键字修饰,则默认为private;
(2)在继承的时候,private、的权限永远不会变,
public继承时,基类的成员权限不变;
protcted继承时,基类的public变为protcted,protected不变。
private时,基类的全部成员权限变为private。

4.构造函数、析构函数,以及不会常用的:拷贝构造函数(主要用于初始化)
构造函数:没有返回值,默认是没有参数的,可以重载为有参数的构造函数,主要执行一些必要的初始化工作。
析构函数:没有返回值,没有参数,主要执行一些清理工作。

5.C++的  类的友元函数
定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。
尽管友元函数的原型有在类的定义中出现过,(声明一个函数为友元函数)但是友元函数并不是类的成员函数。
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

使用关键字friend。
如在类定义中声明:frind void friendfunc(int x);
在类外部定义:如正常函数般定义。

6.内联函数
就是在一种函数,在被编译的时候代码的副本会被拷贝到调用处,一般短小精悍,类似与一般用define 定义的短小宏。
与类的关联:
当在类定义中定义时,即使不用inline关键字,编译器会默认是内联函数,在类外部的内联函数就必须用到inline修饰类。

7.this指针与指向类的指针
this就是一个指向对象本身的指针,一般在类定义的函数中使用。
指向类的指针:class_name *p = new class_name;

8.类的静态成员
就是成员用static定义后,一个类的所有实例都可以访问,相当于在一个类中全局。
要慎用(在一个类A的实例中修改类该静态成员,则另一个类A的实例去访问这个静态成员,也就被改变类,可以作为一个类间通信机制)。

9.拷贝构造函数

 


(二)探究面向对象特性之继承
1.继承的含义、基类与派生类(子类)
继承:就是一个类(派生类)通过一种定义方式,获得另一个类(基类)的成员访问
(具体访问权限根据继承类型和基类的成员访问权限共同决定)

2.继承的形式
单继承
class A{
...
};

class B:public/protcted/private A{//class B public/protcted/private(三者之一)继承class A

};

多继承
若class B在定义时要继承多各类,如类C:
class B:public/protcted/private A,public/protcted/private C{

};
多继承需要注意的是:
若A C中都有一个成员a,那么先继承A的a,会忽略C的a。

3.继承的类型及访问权限

访问            public      protected    private
同一个类    yes      yes            yes
派生类            yes       yes           no
外部的类    yes      no            no

这里还应该注意:
(1)不同的继承类型会决定在派生类中访问基类的权限。
如,基类有public/protcted/private 三种成员,若派生类private继承基类,那么在派生类中,
基类的public/protcted成员在派生类中可以被访问,但是在派生类中变为类private,意味着,这些成员再次被继承时,不能那个被访问。

public与 protected继承同理。

(2)友元函数例外!可以访问与之关联类的所有成员。


几乎不使用 protected private 继承,通常用public 继承。当使用不同类型的继承时,遵循以下几个规则:
公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。

4.多重继承


(三)探究面向对象特性之重载与多态
1.重载、多态及其区别
简而言之:
重载就是一个类定义中定义多个函数名相同,参数不同的重载函数(返回值一般是相等的)
注意:不能仅通过返回类型的不同来重载函数。(会编译error)
多态就是在派生类中覆写基类中存在的成员函数。

2.重载就那么回事儿,但是多态就比较有趣了
多态涉及到:虚函数、抽象、接口、模板、泛型编程等概念

3.虚函数   纯虚函数
虚函数就是在类中使用关键字virtual修饰的函数,虚函数是在基类中定义(可以实现,不实现则为纯虚函数),在派生类中覆写。
形如:
class A{
public:
    virtual void run(){
        this.a = 1;
    }
private:
    int a;
};

或纯虚函数定义:
class A{
public:
    virtual void run()=0;  //纯虚函数是通过在声明中使用 "= 0" 来指定的
private:
    int a;
};

当派生类B继承A的时候,就可以在派生类中覆写这个虚函数类。

4.多态的覆写分类
(1)基类中被覆写的函数不是虚函数
那么,在使用的时候:
A *a = new B;
a.run();   //虽然实例是B,但是在编译的时候早期(静态)绑定了类A,故调用的是A的run

(2)基类中被覆写的函数不是虚函数
同上例子:a.run(); 将执行B的run,这是后期(动态)绑定

5.抽象 与抽象类
抽象就是说:抽象出功能接口给用户,程序员对其功能接口的实现是封装在幕后的,对用户(服务使用者)是透明的。
当一个类中定义了纯虚函数,那么这个类就是抽象类。

6.特别的:运算符重载

可以重定义或重载大部分 C++ 内置的运算符。这样,就能使用自定义类型的运算符。
重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。
与其他函数一样,重载运算符有一个返回类型和一个参数列表。
#include <iostream>
using namespace std;
 
class Box
{
   public:
 
      double getVolume(void)
      {
         return length * breadth * height;
      }
      void setLength( double len )
      {
          length = len;
      }
 
      void setBreadth( double bre )
      {
          breadth = bre;
      }
 
      void setHeight( double hei )
      {
          height = hei;
      }
      // 重载 + 运算符,用于把两个 Box 对象相加
      Box operator+(const Box& b)
      {
         Box box;
         box.length = this->length + b.length;
         box.breadth = this->breadth + b.breadth;
         box.height = this->height + b.height;
         return box;
      }
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};
// 程序的主函数
int main( )
{
   Box Box1;                // 声明 Box1,类型为 Box
   Box Box2;                // 声明 Box2,类型为 Box
   Box Box3;                // 声明 Box3,类型为 Box
   double volume = 0.0;     // 把体积存储在该变量中
 
   // Box1 详述
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);
 
   // Box2 详述
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);
 
   // Box1 的体积
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
 
   // Box2 的体积
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;
 
   // 把两个对象相加,得到 Box3
   Box3 = Box1 + Box2;
 
   // Box3 的体积
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;
 
   return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400

例:
// 重载负运算符( - )
      Distance operator- ()  
      {
         feet = -feet;
         inches = -inches;
         return Distance(feet, inches);
      }
int main()
{
   Distance D1(11, 10), D2(-5, 11);
 
   -D1;                     // 取相反数
   D1.displayDistance();    // 距离 D1
 
   -D2;                     // 取相反数
   D2.displayDistance();    // 距离 D2
 
   return 0;
}

其实这也是多态的一种形式吧,通过重载运算符,使得原本不能作用的对象编成可能。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值