「BUAA-C++」Lec4:static、const和运算符重载


static限定符

static local variable

  • 静态局部变量的特点是”一次构造,永不析构,直到程序结束“。因此静态局部变量可以用来保值,这和全局变量行为相似)
  • 静态变量放在全局变量区
    void func() {
        static int i = 0;
        cout << i++ << endl;
    }
    
    int main() {
        for (int i = 0; i < 10; i++) {
            func()
        }
    }

static function

  • 函数前用static修饰,表示此函数为本文件专用,其他文件无法进行访问
  • 函数默认是全局域,全局变量默认是文件域static可将函数默认的全局域改为文件域
    //a.cpp
    static void function() {
        //.......
    }
    //b.cpp
    void function();
    int main() {
        function(); //报错!!!
        return 0;
    }
    

函数默认是全局域,全局变量默认是文件域,这也就说明为什么我们在使用外部变量(定义在其他文件的变量)前需要用 extern进行声明,而使用外部函数是不需要(当然也是可以的)

static data member

  • 类中可以定义静态变量,一次性初始化,所有对象共享。
  • 类中的静态变量,既可以通过对象访问,也可以通过类名访问
  • 静态变量必须在类外进行初始化,而且只能初始化一次。
  • 不能在构造函数中为静态变量赋值。
    class Static {
    public:
        static int i;
        int j;
        Static(int j) {
            this->j = j;
        }
    };
    
    int Static::i = 1;
    
    int main() {
        Static s1(1), s2(2);
        cout << s1.i <<s2.i << endl;
    }

static function member

  • 类中的静态函数,既可以通过对象访问,也可以通过类名访问
  • 静态函数中没有this指针
  • 静态函数只能访问类中的静态变量,不能访问类的对象。
    class Static {
    public:
        static void print() {
            cout << "static!" << endl;
        }
    }
    
    int main() {
        //通过对象调用
        Static s;
        s.print();
        //通过类名调用
        Static::print();
    }
    

设计模式:单例模式(signleton
单例模式是指某个类全局只有一个对象,一个单例模式的例子如下——

class Single {
   static Single* self //定义一个指向该类唯一对象的指针
   Single(); //构造函数私有化
public:
   static Single* get_instance();
}

Single* Single::self = NULL;
Single* Single::get_instance() { //获取这一对象
   if (self == NULL) {
       self = new Single();
   }
   return self;
}

int main() {
   Single* p = Single::get_instance();
   return 0;
}

const限定符

const parameter

  • 函数参数定义为const, 则只能使用该参数的值,不能改变该参数,也不能将该参数作为左值(l-value)使用。
    void func(const int *p) {
        (*p)++; //error! 不能将(*p)作为左值使用,因为p指向的是const int
    }

const data member

  • 在类中我们将数据成员定义为const,这样的数据成员只读。
  • 对于const数据成员来说,初始化主要有以下两种方法——
    • 使用类内初始值
    • 使用构造函数的初始化列表
      如果同时使用以上两种方式,则已初始化列表中的值为最终初始化结果
  • 不能在构造函数和其他成员函数内部对const数据成员进行赋值!
    class Student{
        const int id;
    };

早期C++中没有const data member这种语法,党史如果要在类中定义常量,一般需要用枚举型enum

const function member

  • 一般来说,const对象是不可以调用函数的,这是为了防止函数会修改const对象中的值。但是如果真的需要其调用函数怎么办(前提是被调用的函数不能修改对象的值)?
  • 我们可以将被调用的函数用const来限定,这样就可以让const对象调用该函数了。写法如下——
    class Student{
    public:
        void fun() const; //const限定符写在最后
    }
    
    void Student::fun() const {
        cout << "const function mumber!" << endl;
    }
    
    int main() {
        const Student s;
        s.func(); //可以进行调用
    }

关于new和delete

  • newmalloc都可以用于动态申请堆空间来建立新对象。但是,new一个对象时会调用该类的构造函数,而malloc不会。因此,newmalloc有以下关系——
    \[new = malloc + construction\]
  • 同理,deletefree也有相似的关系。(注意:destruction应该在free前面)
    \[delete = destruction + free\]

运算符重载

一般情况下, +, -, *, ++, []等运算符只能作用于基本类型,不能作用于对象。但是,我们可以在类中对这些运算符进行重载,这样我们就可以将运算符应用于对象了。重载运算符的写法如下——

[返回值类型] operator [运算符]( 形参表) {

} 

下面以+, ++两个运算符为例,介绍一下具体的写法——
class Account {
    int balance;
    char *name;
public:
    Account(int balance);
    void save(int money);
    //重载运算符,返回自身的引用
    Account& operator + (int money); 
    Account& operator ++; //前++
    Accoutn operator ++ (int); //后+++
};
Account::Account(int balance) {
    this->balance = balance;
}
void Account::save(int money) {
    this->balance += money;
}
//重载运算符+
Account& Account::operator + (int money) { 
    this->save(money);
    return this;
}
//重载运算符++*(前自加)
Account& Account::operator ++ { 
    this->balance++;
    return this}
//重载运算符++*(后自加)
Account Account::operator ++ (int) { 
    Account early = *this;
    this->balance++;
    return early;
}

++这个运算符比较玄学,因为既可以前自加,还可以后自加前自加我们可以直接使用Object& operator ++{}来进行定义。后自加为了与之区分,使用了一个int作为占位参数, 即使用Object& operator ++(int) {}来进行定义(注意只能是int,不能是char或者其他)。

注意在后自加的函数定义中,有一句是Account early = *this;,这句话实际上是通过传值来进行拷贝,会默认调用一个 拷贝构造(在上一节课的笔记中讲过)。本来,这种写法是不推荐的,但是,为了配合后自加"先返回原值,再自加"这一变态的要求,我们又不得不这样写……


作业:使用SQLite,实现一个借书、还书的流程。
ORMapping


文章作者: Hyggge
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Hyggge !
  目录