关闭

C++知识点随笔(三):static、const、friend、inline

标签: staticconstfriendinline
308人阅读 评论(1) 收藏 举报
分类:

一、static

静态成员属性为什么要在类外初始化?
静态成员属性之所以不能在构造函数内初始化,是因为构造函数必须要在定义对象的时候才会调用,而static变量在编译的时候就创建了,所以要在类外通过类名作用域对static成员属性初始化。

注意:sizeof()在C++中和C语言有不同,当我们:

cout << sizeof(//类名) << endl;

的时候,不是输出这个类的大小,而是输出定义一个这个类的对象需要申请多大的空间,所以如果这个类里包含了静态成员都不会计算在sizeof()内的,因为静态成员一个类只有一份儿,所以的对象共用他们。

struct Node
{
    int age;
    char c;
};

class CPeople
{
public:
    int pp;
    static const int qq = 100;   //静态常量整形数据成员才能在类内初始化
    static Node node[2];
    static int num;    // 静态成员一定要在类外初始化
public:      //相当于全局变量,在编译的时候就申请空间了,不用对象也能调用,(类名::)
    CPeople()
    {
        pp = 100;
    }
    //  静态成员函数:不能用普通的成员属性,只能用 static 成员,因为没有this指针
    static void Show()
    {
        //cout << this->pp << endl;     
        cout << num << endl;
        cout << "static::show" << endl;
    }
};
Node CPeople::node[2] = {{123,'d'},{456,'y'}};  //静态结构体数组初始化
int CPeople::num = 123;   //静态成员的初始化

注意:静态常量整形数据成员才能在类内初始化。所以short、long、char都可以,但是float、double不可以。

二、const

非静态const成员属性为什么一定要在初始化列表里进行初始化?
在C中我们知道#define进行预定义的某个数是被分配内存的,其文件在编译预处理过程中就会用定义好的数据去替代文中的符号。但是const却是不一样的,一般情况下编译器也是不为const创建空间的,只是将这个定义的数字保存在符号表中的。所以C++中const是在编译的时候定义的,但是它的初始化可以在调用构造函数(也就是创建对象)的时候通过初始化列表的方式进行。调用构造函数的时候,首先是给该实例(类的具体对象)分配空间。使用初始化列表的话,就在分配空间的时候,同时将其空间初始化。但在构造函数的大括号里,所有变(常)量的空间都已经分配好了,进行赋值操作。我们知道const是常量,只能进行初始化操作而不能进行赋值操作,所以必须在初始化列表中分配空间的同时进行初始化操作。

还有一个赋值次数,效率上的区别,初始化列表在对象初始化时对成员变量赋值一次,而使用构造函数内直接赋值的话,对成员变量赋值两次,一次是对象构造是用默认值进行赋值,第二次是调用构造函数赋值。因为普通成员变量是否初始化都可以,而且允许赋值操作,所以普通成员变量既可以使用初始化列表又可以使用构造函数赋值。

参考:http://blog.csdn.net/zhouyelihua/article/details/23252667

const成员函数

void Show(/*const CPeople* this*/) const   // 常函数,不能修改类中的成员属性
{                               
    //this->a = 100;   //错误,因为 this 已经变成 const CPeople* this
}

常量类型的对象:

const CPeople pep;

只能调用常函数,普通函数用不了,因为我们知道成员函数在使用的时候要把对象的地址传进去,而我们用常量对象调用普通成员变量的时候,相当于:

void AA(/*CPeople* this = const CPeople* ll*/)
{
    a = 567;
}

一定会报错的。而const成员函数的this已经变了,所以常量对象可以调用const成员函数。反过来普通对象可以调用常函数。

三、friend

friend class BB;                // 友元类
friend void Show(CPeople pp);   // 友元函数,可以让这个东西用自己的private成员

无论是友元类还是被友元类,都不能继承这个友元关系。友元的友元也不能使用。友元就是只限定这一个可以用

类的封装性问题
友元函数是破坏类的封装性的最大杀手。我们在使用成员函数返回类的私有成员属性的时候也是很危险的,如果一定要使用的话,就将返回值设为const。

四、inline

void AA()    // 类内实现的都是内联函数(默认的)
{
    cout << "AA" << endl;
}
/*inline */void BB();    //  不是内联的 
inline void BB();    //  内联的

不过编译器自己也会有判断,其实声明为inline只是对编译器提出一个建议,建议编译器进行内联,而具体会不会内联,由编译器决定,编译器会综合考虑更方面因素来判断要不要进行内联。
内联将函数代码直接在调用的地方展开,而函数调用是一个跳转语句,通过函数指针跳转到函数体的地址,执行完再回来,所以inline是一种用空间换时间的方法。

参考我的另一篇博客:http://blog.csdn.net/u012300157/article/details/46763089

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:8370次
    • 积分:441
    • 等级:
    • 排名:千里之外
    • 原创:27篇
    • 转载:5篇
    • 译文:0篇
    • 评论:21条
    文章分类
    最新评论