c++关于静态、常方法的定义与调用和静态、常成员的初始化笔记

一、c++类里的成员,不管是const,还是static成员都不能直接,初始化;如:

class student

{

private:

            int sno=2001;                   //错误

            const int sno=2001;       //错误

            static int sno=2001;       //错误,不能直接初始化成员;

            static const int sno=2001;  //正确,只能给静态常成员直接赋值

};

const int student::sno=88;//正确

静态成员(方法和成员变量)是属于整个类的不属于某个对象,因此静态方法内没有this指针,即静态方法内也就不能直接调用非静态方法,必须通过对象来调用非静态方法。(因为在非静态方法内直接调用非静态方法时,默认使用this指针来调用,而静态方法内没有this指针,因此不能直接调用非静态方法)。在单例里经常看见在静态方法里通过new来调用构造函数,构造函数不是静态的,为什么能调用呢?

这里要明白,1.构造函数本身就不能显示调用(即通过对象或this指针调用),它是在构建对象时,系统调用的。

1)静态成员的初始化,只能在类外初始化

class student

{

public:

             static int sno;

);

int student::sno=1000;//正确,只能这样

且构造函数不能为静态(static)函数;

因为static有两个作用,一个是域限制,一个是生存限制;

域限制:被static修饰的函数,只能本文件中使用。

生存限制:如果是静态类方法,则说明在类对象出生前,类的静态函数就存活着。所以构造函数不能为静态。

类外定义函数时,如果加上static,会编译报错,因为作用域限制只能在该cpp中使用,与类本意冲突,限制类自由。

构造函数也不能为virtual修饰,因为每个类中如果存在virtual函数,那么会维护一张虚函数表(会有一个4个字节虚函数表指针),虚函数调用通过虚函数指针来调用的,如果构造函数为virtual,那么对象都没有实例化,内存空间都没有(虚函数指针不存在),怎么找到虚函数表呢?所以构造函数不能为虚函数。

2)静态函数的定义与调用

class student

{

public:

             static void fun()          //在类中声明和实现;            

             {

                      cout<<"abc"<<endl;

             }

            static int add(int a,int b);       //也可以在类中声明,类外实现

);

//类外实现

int student::add(int a,int b)

{

      return a+b;

}

int main()

{

          //调用静态的fun方法

          student::fun();       

          return 0;

}

注意:在类中用static声明了的方法,在类外实现时,不能写static修饰,会报错;另外,virtual只能在类中声明,和用于虚继承,不能在类外声明,编译报错。

全局函数默认为extern修饰,如果声明时是extern修饰的,实现时,不能用static修饰,编译报错如:声明为int fun();//是extern修饰

实现: static int fun()

        { cout<<"shixian"<<endl;} //会编译报错

当函数声明为static时,实现不用static修饰,该函数也为静态的,限制在该.cpp中如:

static int fun1();

实现如: int fun1()

{ cout<<"as"<<endl; }//fun1为静态函数

3)常成员的初始化,我们熟知常量是其值不能被改变的,一般都是声明时,直接初始化,但在类中不能直接初始化,只能通过构造函数参数列表来进行初始化。如:

class student

{

public:

           const int sno;

           student(int a):sno(a)         //这样初始化常成员

           {}

};

4)常方法的声明与定义,常方法里是不能改变所有成员的值,因此,不能调用非常方法(它们有的会改变成员的值);常方法仅仅只是不能成员的值(mutable修饰的除外)

class student

{

private:

            int a;

            mutable int b;

public:

           const int add(int a,int b);               //这个并不是常方法,这只是返回值为const int型的普通函数

           //常方法的声明

           int add(string a,string b) const    //在其函数后加const

          {

                        a=10;               //这是错的,常方法里是不能改变 所有成员的值(除了用mutable修饰的成员外)

                         b=10;             //对的,用mutable修饰的可以在常方法里改变其值

         }

         int  f1() const;    //类中只声明常方法,类外实现

};

int  student::f1() const   //同样要在后面加上const修饰

{

return 22;

}

二、此外我们来类比下常量指针和指针常量,以及常引用,和常对象   (常量是不能作为左值)

例如:

const char* s;             //表示常量指针,说明*s表示一个常量,通过*s其值不能被改变,所以不能同过*s来给s所指向的地址赋值,但是,s是变量,它的值是可以

                                       被改变的,即s的指向是能被赋值的

char* const s;          //表示指针常量,说明s是一个常量,通过s其值是不能被改变的,所以s所指的位置是不变的,但是*s是变量,它的值是可变的,可以通过*s给s所指向的地址赋值

const int& a=b;        //表示常引用,a是常引用(等价于常量),通过a不能改变其值,所以不用它来给变量b赋值,但变量b是可以赋值的

                                   注意:引用相当于变量的别名(另一个名字),不占另外的内存空间,和该变量同一地址;另外引用在声明的时候必须要初始化,一个引用只能属于一个变量的引用,且后面不能再给该引用引用其它变量;

const student stu;  // student是一个类名,stu表示常对象,即是常量,通过stu其值不会被改变(即通过它,对象里的成员值也不会变),所以常对象只能调用常方法;

const student* strstu; //常对象指针,所指向的是一个常对象,通过strstu指针不能改变其指向对象的值,*strstu(即strstu->)和上面等效;只能调用常方法。

注意:临时变量(即无名的变量)的引用必须是常引用。如:

int fun()

{

return 9;

}

 int & a = fun();//错误,编译都通不过,fun返回一个临时的值,必须得用const 引用。

const int& a = fun();//正确;

尽可能不要用引用局部变量,虽然,常引用也能引用局部变量,但是局部变量在函数结束后会被释放掉,此时,在使用引用会出现访问非法地址的错误。

 非常引用初始化时,必须用左值(可以被赋值的变量,不能是常量(const修饰))进行初始化,如:

int s;

int & a = s;//正确;

int & b= 19; //错误;

常引用初始化时,可以用常量初始化,

const int &c = 10;//正确;临时的无名对象只能用常引用。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值