C++中有关 const & 内敛 & 友元&静态成员 的用法比较杂乱,算是C++中一个麻烦的部分。现速速的对它们作大体的总结,了解它们当中常见的用法和陷阱。ios
在成员函数后面加const,const修饰this指针所指向的对象,也就是保证调用这个const成员函数的对象在函数内不会改变安全
/************************************************************************* > File Name: 2.cc > Author: tp > Mail: > Created Time: Tue 19 Jun 2018 05:48:12 PM CST ************************************************************************/ #include <iostream> #include <cstdio> #include <vector>
using namespace std; class Date { public : Date(int y=0, int m =0, int d=0) :_year(y),_month( m),_day( d){ } void Display ( ) { cout<<" Display ( ) " <<endl; cout<<" year:" <<_year<< endl; cout<<" month:" <<_month<< endl; cout<<" day:" <<_day<< endl<<endl ; } void Display ( ) const { cout<<" Display ( ) const" <<endl; cout<<" year:" <<_year<< endl; cout<<" month:" <<_month<< endl; cout<<" day:" <<_day<< endl<<endl; } private : int _year ; // 年
int _month ; // 月
int _day ; // 日
}; int main( ) { Date d1; d1.Display ( ) ; const Date d2; d2.Display(); return 0; }
常见情景:函数
1. const对象能够调用非const成员函数和const成员函数吗?优化
只能调用const成员函数。由于是const对象,它就要求对象内部数据初始化好不会改变,因此其相应成员函数也应由const修饰。this
#include <iostream> #include <cstdio> #include <vector> using namespace std; class Date { public : Date(int y=0, int m =0, int d=0) :_year(y),_month( m),_day( d){ } void Display ( ) { cout<<" Display ( ) " <<endl; cout<<" year:" <<_year<< endl; cout<<" month:" <<_month<< endl; cout<<" day:" <<_day<< endl<<endl; } private : int _year ; // 年 int _month ; // 月 int _day ; // 日 }; int main( ) { // Date d1; // d1.Display ( ) ; const Date d2; d2.Display(); return 0; } //结果:报错!
2. 非const对象能够调用非const成员函数和const成员函数吗?spa
均可以调用。调用非const成员函数没有争议,当非const对象调用const成员函数时,对非const对象来讲,这实际上是一个权限的缩小,是能够完成的。debug
#include <iostream> #include <cstdio> #include <vector> using namespace std; class Date { public : Date(int y=0, int m =0, int d=0) :_year(y),_month( m),_day( d){ } void Display ( ) const { cout<<" Display ( ) const" <<endl; cout<<" year:" <<_year<< endl; cout<<" month:" <<_month<< endl; cout<<" day:" <<_day<< endl<<endl; } private : int _year ; // 年 int _month ; // 月 int _day ; // 日 }; int main( ) { Date d1; d1.Display ( ) ; // const Date d2; // d2.Display(); return 0; } //结果:成功调用
3. const成员函数内能够调用其它的const成员函数非const成员函数吗?指针
在const成员函数中是不能调用非const成员函数。道理同上
4. 非const成员函数内能够调用其它的const成员函数非const成员函数吗?调试
非const成员函数既能够掉非const成员函数 也能够调用const成员函数(道理类似,非const成员函数至关于一次权限缩小)code
关于内敛,内敛就是以inline修饰的函数叫作内联函数,编译时C++编译器会在调用内联函数的地方插入代码进行展开,没有
函数压栈的开销,内联函数提高程序运行的效率。
关于内敛的几点注意:
·inline是一种以空间换时间的作法,省去调用函数额开销。因此代码很长或者有循环/递归的的函数不适宜使用内联。
·inline对于编译器而言只是一个建议,编译器会自动优化,若是定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉内联。
·inline必须和函数定义放在一块儿,才能成为内联函数,仅仅将inline关键字放到声明前是不起做用的。
·定义在类内的成员函数默认为内联函数。
·debug版本下的内敛函数不展开,因此它能够像普通函数那样进行调试。
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() // 全局函数定义为内联
{}
内敛和宏区别:
·最大的区别在于宏是在预处理阶段处理,而内敛是在编译阶段来进行处理。
·预处理阶段发生宏替换,但替换仅仅是单纯的文本替换,不做类型安全的检查,同时它也不能去访存私有的数据成员;
·而内敛在编译阶段进行的处理,它有类型安全的检查(即调用一个内联函数时,编译器首先确保正确,即全部的参数类型必须是正确的或者编译器必须可以将类型转换为正确类型,而且返回值在目标表达式里应该是正确的类型或者能够改变为正确的类型),同时也能够访存私有的数据成员。
总结来讲就是内敛能够像宏同样能够提升代码执行效率,但内敛还能够进行类型安全检查,访问私有数据成员,因此可尽可能用内敛去替代宏。
在C++中友元函数容许在类外访问该类中的任何成员,就象成员函数同样,友元函数用关键字friend说明。
关于友元:
1. 友元函数不是类的成员函数。
2. 友元函数能够经过对象访问全部成员,私有和保护成员也同样。
一个典型的例子:
重载自定义类型的输入(>>) 输出(<<)
class Date { public : // operator<<不能为成员函数 // 返回值定义为输入输出流的引用。
friend ostream& operator<< ( ostream& os , const Date& d ); friend istream& operator>> ( istream& is , Date& d); private : int _year ; // 年
int _month ; // 月
int _day ; // 日
}; ostream& operator<<( ostream& os , const Date& d) { os<<"year:" <<d. _year<<endl ; os<<"month:" <<d. _month<<endl ; os<<"day:" <<d. _day<<endl <<endl; return os ; } // cin.operator<<(cin, d1) istream& operator>> ( istream& is , Date& d) { cout<<" 请分别输入年月日: "<<endl ; is>>d ._year; is>>d ._month; is>>d ._day; return is ; } void Test () { Date d1 ; cin>>d1 ; cout<<d1 ; }
为何说<<, >>操做符重载函数 不能是成员函数?
class Date { public : ostream& operator<< (ostream& os) ; istream& operator>> (istream& is) ; private : int _year ; // 年
int _month ; // 月
int _day ; // 日
} ; ostream& Date::operator<<(ostream& os) { os<<" year:" << _year<<endl ; os<<" month:" << _month<<endl ; os<<" day:" << _day<<endl <<endl; return os ; } // cin.operator<<( cin, d1)
istream& Date::operator>> (istream& is) { cout<<" 请分别输入年月日: " <<endl ; is>>_year; is>>_month; is>>_day; return is ; } void Test ( ) { Date d1 ; d1>>cin; d1<<cout; }
不难注意到最后咱们调用>> <<操做符时,将成为一种怪异的操做!估计是难以让人接受的。
究其缘由,不难发现实际上是由this指针致使的。由于this指针会默认会用成员函数的第一个位置,其它传进来的参数(这里的ostream 、istream)都只能溜到它后面去玩,因此才会导致cin、cout跑到“>>”,"<<"的右边去。想要像正常状况那样使用cin cout,咱们就只有不把它们写成成员函数了,这样就没有this指针来抢位子了。可是,这无疑又将引来一个问题:因为函数须要访问传入进来的输入、输出对象,但此时对象的成员是被封装的,函数访问必然就会失败。
因此最后要解决这个问题,咱们就只有将“opetator >>”,"operator<<"函数定义为Date类的友元函数了,这样即可经过对象来访问其中的数据成员了,最后完成目的。
从这里也容易看出用友元,实际上是一种破坏封装的行为。
除此友元函数以外还有友元类
友元类:整个类能够是另外一个类的友元。友元类的每一个成员函数都是另外一个类的友元函数,均可访问另外一个类中的保护或私有数据成员。
类里面static修饰的成员,成为静态类成员。它最大的特色就是:类的静态成员是该类型的全部对象对象所共享。
注意:静态成员函数没有隐含的this指针参数,因此可使用类型::做用域访问符直接调用静态成员函数。
#include <iostream> #include <cstdio> #include <vector>
using namespace std; class Date { public : Date() { cout<<"Date( )"<<endl; ++dCount; } static void printCount( ) { cout<<"Date::dCount:"<<dCount<<endl;; } private : static int dCount; } ; //定义并初始化静态成员
int Date::dCount = 0; void Test( ) { Date d1 ; d1.printCount( ); //1
Date d2 ; Date d3 ; //能够直接用类名加类域限定符调用
Date::printCount( ); //3
}
关于静态成员一点思考:
1. 静态成员函数能够访问非静态的成员吗?
不能够,由于静态成员函数没有this指针。因为非静态数据成员是存储在对象中,成员函数访问数据成员要借助this指针,因此没有this指针的静态成员函数不能访问非静态数据成员。
2. 非静态的成员函数能够访问静态成员吗?
能够的,静态数据成员存储在地址空间的数据段,它为该类的全部对象共享,这些对象的成员函数天然也能够访问。