zoukankan      html  css  js  c++  java
  • C++笔记(2)面向对象编程

    . 面向对象编程

     

    virtual函数,启用动态绑定,只需在类内部的成员函数中声明,不能用在类定义体外部的函数定义中.

    protected成员

    可以被派生类对象访问, 其余同private权限. 派生类只能通过派生类对象访问其基类的protected成员,派生类对其基类类型的对象的protected没有访问权限.

     

    2.1 派生类

    myclass.h文件

     class myclass
    {
          
          public:
            
            operator int () const {return m_i;} //转换操作符
    
          friend class otherclass; //友元
          
          myclass():m_i(0), m_i(0.5), m_i2(0){m_i = 0; …} /*初始化,无返回值,不能声明为const,
          
          初始化列表一定会先于函数体执行,无论显示或隐式初始化,此时成员变量已经有值.
          
          如果没有对成员变量显示初始化,编译器会隐式地使用成员类型的默认构造函数,
          
          内置类型无默认构造函数,则编译器尝试隐式初始化失败,此时必须显示初始化或在函数体中赋值.
          
          无默认构造函数的类类型成员,以及const或者引用类型成员,必须在构造函数初始化列表中初始化.
          
          成员初始化顺序是定义成员的顺序.
          
          如果无构造函数,编译器会生成默认构造函数,如果有显示定义构造函数,则编译器不会生成默认构造函数.*/
    
          myclass(int i):m_i2(0),m_i(i){} //可被重载
          
          bool inlinefunc() {...} //inline函数
    
             inline void func1(); //inline函数,可以在声明中引用inline,也可在定义中引用
          
          const myclass& func2() const; /*普通成员函数,返回调用对象的引用,const成员函数必须返回const对象的引用.const对象只能使用const func2()成员函数.非const对象也可调用.*/
          
          myclass func2(int i); //重载函数
          
          myclass& func2(); /*重载函数,非const对象可以调用,非const对象调用fun2()函数时,非const func2()成员函数优先级大于const func2()成员函数.*/
          
          typedef  int MYINT;
          
          MYINT func3(MYINT i);
          
          bool equal(myclass m);
          
          static void staticfunc(void);
          
          virtual void virtualfunc(void);
          
          virtual void virtualfunc2(void);
      void func3(void);
    public: int m_i2; private: const int m_i; //const成员变量,必须在构造函数初始化列表中初始化. static float m_f; //static 成员变量 myclass *m_class; //前向声明 mutable char c; //可变数据成员,在const成员函数中也可以修改. static myclass m_static_class; //static可以是该成员所属的类类型. //myclass m_class; //error };

     

    deriveclass.h文件

    class deriveclass: privated/public/protected superclass

    {

             自己的成员函数;

             继承的成员函数;

             自己的成员变量;

             继承的成员变量; //在派生类中可以使用publicprotected,但是不能访问privated.

    };

     

    2.2 虚函数

     

     虚函数是在运行时期才确定;非虚函数在编译时期根据对象确定。

    函数名字的查找的继承:首先确定调用函数的对象,引用和指针类型,如果在该类中查找不到此函数,则在基类链中寻找,如果找不到,则编译报错,找到了就执行常规函数检查是否调用合法;

    如果合法,编译器生成代码,如果是通过引用和指针调用且为虚函数,则编译器生成代码以确定对象的动态类型运行哪个版本,否则直接生成代码调用函数。

     1 class derivedclass :public myclass
    2
    3 {
    4
    5 public:
    6
    7 derivedclass(void): m_di(0), myclass(); //首先调用各基类的构造函数,
    8
    9 virtual ~derivedclass(void); /*首先运行派生类的析构函数,然后按继承层次一次向上调用各基类析构函数. */
    10
    11 void virtualfunc(void); /*如果需要调用基类的函数,必须明确使用域操作符 obj->myclass::virtualfunc();*/
    12
    13 void virtualfunc2(int); /*没有重定义虚函数virtualfunc2(),所以virtualfunc2(int)屏蔽virtualfunc2(),
                      derivedclass dc; 不能直接调用dc.virtualfunc2(). 必须通过作用域操作符::, dc.myclass::virtualfunc(); 但是动态绑定可以调用:derivedclass dc; myclass *pmc = &dc; pmc->virtualfunc2()
    */
    14
    15/*对于非虚函数,在编译时期根据调用该函数的对象,引用或者指针类型而确定,所以如果是动态绑定,derivedclass dc; myclass *pmc = &dc; pmc->func3()实际调用的是基类的func3(),*/
       void func3(void);

    16
    17
    18
    19 derivedclass(const derivedclass & d): myclass(d), m_di(d.m_di), c(0){}
    20
    21 //复制构造函数
    22
    23 derivedclass& operator = (const derivedclass &d) //赋值操作符
    24
    25 {
    26
    27 if (this != &d)
    28
    29 {
    30
    31 myclass::operator = (d);
    32
    33 m_di = d.m_di;
    34
    35 }
    36
    37 return *this;
    38
    39 }
    40
    41
    42
    43 private:
    44
    45 int m_di; //自己的成员变量;
    46
    47 mutable char c; /*与基类成员同名,屏蔽基类成员, 但是可以通过myclass::c访问被屏蔽的基类成员c. */
    48
    49 };



    派生类中虚函数的声明必须与基类中的定义方式完全匹配,有一个例外:返回基类型的引用(或指针)的虚函数.派生类中的虚函数可以返回基类函数所返回类型的派生类的引用(或指针). 即可返回基类或派生类的引用或指针.

     

    一旦在基类声明为虚函数, 派生类中也是虚函数.

     

    函数调用触发动态绑定动态必须满足两个条件,第一必须指定为虚函数,第二不许通过基类类型的引用或指针进行函数调用.

     

    可将基类类型的引用绑定至派生类对象的基类部分,也可用基类指针指向派生类对象. 运行时才能确定实际类型. 编译其编译的时候都当作基类类型对象,

     

     

     1 myclass& func(const myclass& obj);
    2
    3 myclass& func(const myclass* obj);
    4
    5 myclass superobj;
    6
    7 func(superobj);
    8
    9 myclass * psuperobj = &superobj;
    10
    11 func(psuperobj);
    12
    13 //动态绑定:
    14
    15 derivedclass derivedobj;
    16
    17 func(derivedobj); /*引用的是派生类的基类部分,如果调用派生类定义的成员则出错. */
    18
    19 psuperobj = &derivedobj;
    20
    21 func(psuperobj); /*指针指向的是派生类中的基类部分,如果调用派生类定义的成员则出错. */
    22
    23 psuperobj-> virtualfunc(); //运行是才能确定,调用与动态类型对应的函数
    24
    25 psuperobj->derivedfunc(); /*出错, 在编译时期确定的类型为myclass,所以只能访问基类部分. */
    26
    27
    28
    29 myclass& func2(myclass obj);
    30
    31 func2(derivedobj); /*派生类对象传递给基类对象,派生类对象被切割,形参在编译和运行的时候都是基类类型对象, 派生类对象的基类部分被复制到基类对象(通过基类构造函数复制到临时变量. */


     

    构造函数和复制控制成员不能继承. 除了初始化自己的成员以外,还要通过基类的构造函数初始化基类的成员,可以使用合成的默认构造函数. 不能直接调用基类的基类的构造函数初始化基类的基类.

     

    2.3 虚析构函数

     

    virtual~derivedclass(void);

    析构动态绑定对象时, 需要虚析构函数保证运行适当的析构函数.

    构造函数不能定义为虚函数, 因为构造函数是在对象完全构造之前运行的,在构造函数运行的时候,对象的动态类型并不完整.

    赋值操作符也不要定义为虚函数, 因为虚函数必须在基类和派生类中具有同样的形参,形参为基类对象的引用.

     

    1 class derivedclass : private myclass
    2
    3 {
    4
    5 public:
    6
    7 using int m_i2; /*可以使用using声明, 修改恢复成员的访问级别,但不能使访问级别比基类中原来指定的更严格或者宽松. */
    8
    9 }



     

    2.4 纯虚函数

     

    1 class purevirtualclass //抽象基类
    2
    3 {
    4
    5 public:
    6
    7 void purevirtualfunc(myclass mine) const = 0; //纯虚函数
    8
    9 };



    纯虚函数为派生类提供了可以覆盖的接口,但是这个类中的版本绝不会调用,而且不能创建purevirtualclass的类对象.

    如果派生类没有实现纯虚函数,则派生类也为抽象类.

  • 相关阅读:
    HTML多余字符省略号显示,获取jstl表达式传过来的值(内容)
    去除layui表头右边的功能键
    常用正则表达式
    layui注册页面
    怎样将写入到input框中的数据显示到页面上
    layui 添加功能
    python3 -- 去除字符串头尾字符 strip()
    Linux -- tar 命令
    PyMySql -- 常用方法
    MySQL -- 目录
  • 原文地址:https://www.cnblogs.com/zengyou/p/2195583.html
Copyright © 2011-2022 走看看