const成员函数、内联、友元、静态成员、优化

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

#include<iostream>
using namespace std;

class Data  //日期类 
{
public:
    Data(int year=1998, int month=1, int day=1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    void show()
    {
        cout << "正常函数:" ;
        cout << _year << "-" << _month << "-" << _day << endl;
    }
    void show() const
    {
        cout << "const 修饰函数:" ;
        cout << _year << "-" << _month << "-" << _day << endl;
    }
private: 
    int _year;
    int _month;
    int _day;
};

int main()
{
    Data d1(2018, 1, 1);    //调用非const成员函数
    const Data d2(2018, 6, 11);//调用const成员函数
    d1.show();//d1.show(&d1)->Data*
    d2.show();//d2.show(&d2)->const Data*
    system("pause");
    return 0;
}

这里写图片描述
这里写图片描述
注意以下几种场景:
1.const对象不可以调用非const成员函数,可以调用const成员函数。
2.非const对象可以调用非const成员函数和const成员函数。
3.const成员函数内不可以调用其他非const成员函数(const Data *this不可以给Data *this)。
4.非const成员函数内可以调用其他const成员函数(Data *this可以给const Data *this)。
inline(内联)
以inline修饰的函数叫做内联函数,编译时C++编译器会调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。
1. inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的的函数不适宜使用内联。
2. inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉
内联。
3.定义在类内的成员函数默认为定义为内联函数。

class Date
{
public :
void Func () // 定义在类内部默认为内联函数
{}
void Display ();
private :
int _year ; // 年
int _month ; // 月
int _day ; // 日
};
inline void Date::Display () // 成员函数定义为内联
{
cout<<"year:" <<_year<< endl;
cout<<"month:" <<_month<< endl;
cout<<"day:" <<_day<< endl;
}
inline void Test() // 全局函数定义为内联

注:尽量以const、enum、inline替换#define。
问题–C++建议以const/枚举/内联去替代宏,为什么?
宏的优点:
1. 增强代码的复用性。
2. 提高性能。
宏也有很多缺点:
1. 不方便调试宏。(因为预编译阶段进行了替换)
2. 导致代码可读性差,可维护性差,容易误用
3. 没有类型安全的检查。

友元
友元函数:
在C++中友元函数允许在类外访问该类中的任何成员,就象成员函数一样,友元函数用关键字friend说明。
1. 友元函数不是类的成员函数。
2. 友元函数可以通过对象访问所有成员,私有和保护成员也一样。

class Data
{
    friend void Show(const Data& d);//使类外函数show成为类的朋友,就可以访问类私有成员变量
private:
        int _year;
        int _month;
        int _day;
};
void Show(const Data& d) //如果不是类的朋友,类外函数不可以访问类私有成员变量
{
    cout << d._year << "-" << d._month << "-" << d._day << endl;
}

友元类
友元类指整个类可以是另一个类的友元。友元类的每个成员函数都是另一个类的友元函数,都可以访问另一个类中的保护或私有数据成员。

class Time  //时间类
{
    friend class Data;  //类Data是类Time的友元,Data可以访问类Time任何变量
private:
    int _hour;
    int _minute;
    int _second;
};
class Data //日期类
{
public:
    void show()
    {
        cout << _year << "-" << _month << "-" << _day << endl;
        //定义为友元类后,可以访问Time类对象的所有成员
        cout << "hour:" << _t._hour<< endl;//
        cout << "minute:" << _t._minute << endl;
        cout << "second:" << _t._second << endl;        
    }
private:
        int _year;
        int _month;
        int _day;
        Time _t;//声明时间对象变量
};

输入输出运算符的重载的友元函数
cin
这里写图片描述
即cin是标准输入流,是类istream的对象;
cout:
这里写图片描述
即cout是标准输出流,是类ostream的对象。
输入输出运算符重载:operator<< operator >>
1.输入输出运算符重载可以定义为成员函数吗?
由于成员函数有一个默认的this指针形参,在对象调用成员函数时,对象地址作实参传递给成员函数的第一个形参this,那么cout<

class Data 
{
    friend ostream& operator<<(ostream& os, const Data& d);//友元函数
    friend istream& operator >> (istream& is, Data& d); //友元函数
private:
    int _year;
    int _month;
    int _day;
};
ostream& operator<<(ostream& os, const Data& d) //将d输出到os中
//由于os,d都是对象,用引用少拷贝一次,且对象d不修改,用const修饰
{
    os << "year:" << d._year << endl;
    os << "month:" << d._month << endl;
    os << "day:" << d._day << endl;
    return os;
}
istream& operator >> (istream& is, Data& d) //输入到is中
{//由于os,d都是对象,用引用少拷贝一次,且对象d要修改,给其输入,不能用const修饰
    cout << "请分别输入年月日:" << endl;
    is >> d._year;
    is >> d._month;
    is >> d._day;
    return is;
}
int main()
{
    Data d1;
    cin >> d1;
    cout << d1;
    system("pause");
    return 0;
}

2.返回值可以是void,即void operator<<(ostream& os, const Data& d,因为形参os是cout的别名,os改,cout也会改。同理:void operator >> (istream& is, Data& d) ;
注:友元一定程度上破坏了c++的封装,友元不宜多用,在恰当的地方使用友元。
类的静态成员
1.类里面static修饰的成员,称为静态成员。
2.类的静态成员是该类型的所有对象所共享,即计算对象大小时,不计算静态变量大小,和成员函数一样。
静态成员的定义和使用:

class Data
{
public:
    Data()//构造函数
    {
        ++sCount;
    }
    static void PrintCount()//静态成员函数
    {
        cout << sCount << endl;
    }
private:
        int _year;
        int _month;
        int _day;
private:
    static int sCount;//静态成员变量声明,统计创建对象个数
};
int Data::sCount = 0;//定义并初始化静态成员变量
int main()
{
    Data d1;
    Data d2;
    d1.PrintCount();//2
    Data::PrintCount();//2
    //由于静态成员函数没有隐含this指针,所以可以使用类型::作用域访问符直接调用静态成员函数。
    d2.PrintCount();//2
    system("pause");
    return 0;
}

问题:
1.静态成员函数可以访问非静态的成员吗?
不可以,静态成员函数没有this指针,无法确定对象。
2.非静态成员函数可以访问静态的成员吗?
可以。
构造函数拷贝赋值函数的N种调用情况
请看下列题:
Test1中调用了( )次AA的拷贝构造函数,( )次AA的赋值运算符函数的重载。
Test2中调用了( )次AA的拷贝构造函数,( )次AA的赋值运算符函数的重载。
Test3中调用了( )次AA的拷贝构造函数,( )次AA的赋值运算符函数的重载。
class AA
{};
AA f (AA a)
{
return a ;
}
void Test1 ()
{
AA a1 ;
a1 = f(a1);
}
void Test2 ()
{
AA a1 ;
AA a2 = f(a1);
}

void Test3 ()
{
AA a1 ;
AA a2 = f(f(a1));
}
解释如下:
Test1中调用了2次AA的拷贝构造函数,1次AA的赋值运算符函数的重载。
这里写图片描述
Test2中调用了2次AA的拷贝构造函数,_0次AA的赋值运算符函数的重载。
这里写图片描述
Test3中调用了_3次AA的拷贝构造函数,__0次AA的赋值运算符函数的重载。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/sophia__yu/article/details/80653507