您的位置:首页 > 其它

类和对象之再体验-------const&内联&静态成员&友元

2018-01-29 22:40 281 查看
一  const修饰成员函数

先看下我们之前对const的了解  



在成员函数后面加const,const修饰this指针所指向的对象,也就是保证调用这个const成员函数的对象在函数内不会改变





const对象不能掉非const成员函数(对象本来不能改,调非const可以改权限放大不可以),const对象可以调const成员函数

非const对象可以调const成员函数(权限缩小可以),非const对象可以调非const成员函数

const成员函数内可以调用其他的const成员函数,但不能调非const成员函数(权限被放大,不可以)

非const成员函数内可以调用其他的非const成员函数,也可以调用其他的const成员函数(权限放小,可以)



二 内联函数inline

定义:被inline修饰的函数叫做内联函数,编译时编译器会在调用内联函数的地方展开(展开的是指令,并不是代码),没有函数压栈的开销,内敛函数是提升程序运行效率。

1.inline是一种以空间换取时间的做法,省去调用函数的栈帧开销,所以如果代码很长或者有循环/递归的函数不适宜使用内联

2.inline对于编译器只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归,编译器会自动优化掉内联

3.inline必须和函数定义放在一起,才能成为内联函数,仅将inline放在声明前是不起作用

4.定义在类内的成员函数默认定义为内联函数

在c语言学习时我们也接触到宏,宏也省去了函数调用栈帧的开销,提高了效率。

我们先来回顾以下宏:优点1.增强代码复用性  2.提高性能

                                缺点:1.不方便调试宏(预编译阶段进行了替换)2.没有类型安全的检查3.代码膨胀

                                           4.导致代码可读性差,可维护性差,容易误用

宏和普通函数调用的区别:

1.宏只做简单的字符串替换,函数是参数传递,所以必然有参数类型检查

2.宏不经过计算直接替换参数,函数调用则是将参数表达式求值再传递给形参

3宏在编译前进行,即先替换再编译,而函数是编译后在执行时才调用。宏占编译时间,而函数占执行时间

4.函数调用需要保留现场,然后转入调用函数执行,执行完毕后继续返回主调函数,这些耗费在宏中是没有的

5.宏参数不占空间因为只做字符串替换,而函数调用时参数传递是变量之间的传递,形参作为局部变量占用内存空间

宏和内联函数的异同:

同:宏和内联函数都可以节省在函数调用方面的时间,和空间开销,都是提高效率

异:1.在使用时宏只做简单的字符串替换,而内联函数可以进行参数类型的检查,且具有返回值

       2.内联函数首先是函数,函数的许多性质都适用于内联函数

       3.内联函数可以作为某个类的成员函数,这样可以使用类的保护成员和私有成员

       4.内联函数展开的是指令,而不是语句,在debug不展开,在release展开。因此内联函数可以调试,宏不可以

看下面几个易错的面试题



看如上代码用宏实现了一个交换功能,而且结果也没有问题,继续往下看



这时为什么呢,宏在一个域内展开了两次,tmp被多次初始话。继续往下看,



这又是为什莫错了,因为if控制后面一句,宏展开成了三句,因此错了。思考如何改正,见下图,给宏加上{},表示一个新的域



最标准应该如此实现



写一个宏函数实现相加,如下图不能去掉括号否则出错



三  友元

在C++中友元函数允许在类外访问类中的任何成员,就像成员函数一样,友元函数用关键字friend说明

1.友元函数不是类的成员函数

2.友元函数可以通过对象访问所有成员,私有和保护成员也一样(谁想访问,就把谁定义为友元)



    友元一定程度上破坏了类的封装性。友元不宜多用         

输入输出运算符重载实现,能不能实现成类成员函数。可以是可以不过调用的时候必须是d<<cout,行为不符合可读性,

定义成成员函数,输出时是”d<<cout“对象在前面,原因是因为this指针占据了第一个参数,而类成员函数第一个参数都是this,因此输入输出运算符不能定义为成员函数,而应定义成类外全局函数,但是在类外又访问不了类的私有成员变量,因此借助友元。上述两种实现都实现如下





四  类的静态成员

1.类里面static修饰的成员(成员函数,成员变量),称为静态成员

2.类的静态成员属于类,不属于某一对象,为所有对象所共享

(1)静态成员变量

     1.1静态成员变量属于类,普通数据成员属于某一对象

     1.2在类中不给静态数据成员(静态成员变量)分配内存空间

     1.3静态数据成员(静态成员变量)不能再类中进行初始化,再类内仅仅是声明(不分配空间),在类外进行定义和初始化

     1.4静态数据成员(静态成员变量)与静态变量一样,是在编译时创建并初始化,它在该类的任何对象被建立之前就存在。

      1.5私有静态数据成员不能被类外部函数访问,也不能用对象进行访问

(2)静态成员函数

        2.1 定义格式:static 返回值类型  静态成员函数名 (实参表)

        2.2公有静态成员函数的访问格式:

               1.类名::静态成员函数名(因为没有this指针)

               2.对象.静态成员函数名

               3.对象指针->静态成员函数名

        2.3静态成员函数可以定义为类内,也可以定义在类外。(类外定义时不需要加static前缀)

       2.4在一般的成员函数中,都隐含一个this指针,都指向对象自身,而静态成员函数中是没有this指针参数的 (因此不能访问               非静态成员变量和非静态成员函数)而非静态的成员函数可以访问静态成员 (静态成员属于类)        #include<iostream>
using namespace std;
class Date
{
public:Date(int year = 0, int month = 0, int day = 0)//构造
{
// cout << " Date()" << endl;
count++;
}
void Print()
{
cout << _year << " " << _month << " " << _day << endl;
}
static void Printcount()
{
cout << "count " << count << endl;
}
public:
int _year; //声明
int _month;//声明
int _day;//声明
static int count;//静态区 声明

};
int Date:: count = 0;//定义静态变量并初始化
int main()
{

Date d1(2017,10,9);//对象才定义出来年月日
cout << sizeof(d1) << endl;//12
cout << sizeof(Date) << endl;//12
d1.Printcount();//访问静态成员函数
Date::Printcount();//访问静态成员函数
cout << d1.count << endl;//访问成员变量
cout << Date::count << endl;//访问成员变量
system("pause");
return 0;
}
   3.  由上图可知类的大小是只算类成员变量,不算静态成员变量,静态成员变量属于类不属于某个对象

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: