美文网首页每天写500字每周500字
[C++11阅读][1-2-3]提高代码稳定性(中)

[C++11阅读][1-2-3]提高代码稳定性(中)

作者: 凌霄阁2010 | 来源:发表于2020-05-17 09:09 被阅读0次

    非静态成员的sizeof

    与上一篇文章提到的就地初始化成员变量一起去理解。
    我理解这是对原有标准进行完善,提高可用性。
    C++98可以用类名::静态变量的方式计算sizeof,但不能计算非静态变量,非静态变量必须要实例化一个出来才行,比如这样,强制转出一个People实例。

    sizeof(((People*)0)->head);
    

    C++11没这个限制,都可以用类名访问。

    #include <iostream>
    using namespace std;
    struct People {
    public:
        int hand;
        static People * all;    
    };
    int main() {
        People p;
        cout << sizeof(p.hand) << endl;  // 4,C++98通过,C++11通过
        cout << sizeof(People::all) << endl;  // 8,C++98通过,C++11通过
        cout << sizeof(People::hand) << endl;  // 4,C++98不通过,C++11通过,但实测g++是可以通过的
    }
    

    friend支持为类模板声明友元

    先回顾下friend关键字,friend关键字用于声明类的友元,友元可以无视类中成员的属性,无论是public、protected、private,都可以访问。
    友元是单向的,在A里写了friend B,表示B是A的友元,可以访问A私有变量,但A不是B的友元。

    class Poly;
    typedef Poly P;
    class LiLei
    {
        friend class Poly;  // C++98通过,C++11通过
    };
    class Jim
    {
        friend Poly;  // C++98失败,C++11通过,但实测g++能过
    };
    class HanMeiMei
    {
        friend P;  // C++98失败,C++11通过,但实测g++能过
    };
    

    这个特性跟前面一样,我理解这是对原有标准进行完善,提高可用性。
    C++11声明友元时可以省略class关键字,或者用typedef后的名字声明。
    好处是可以为类模板声明友元了,类模板相当于typedef后的名字。

    class P;
    template <typename T> class People
    {
        friend T;  // 实测g++这句话能过
    };
    People<P> PP;  // 类型P成为了People的友元
    People<int> Pi;  // 友元声明int被忽略,int不是类
    

    final/override控制

    final含义是不可继承,放在类名后面指类不可再被继承,放在虚函数的函数名后面说明函数不可再被继承。
    https://zh.cppreference.com/w/cpp/language/final

    struct Base
    {
        virtual void foo();
    };
    struct A : Base
    {
        void foo() final; // Base::foo 被覆盖而 A::foo 是最终覆盖函数
        void bar() final; // 错误: bar 不能为 final 因为它非虚
    };
    struct B final : A // struct B 为 final
    {
        void foo() override; // 错误:foo 不能被覆盖,因为它在 A 中是 final
    };
    struct C : B // 错误:B 为 final
    {
    };
    

    我的补充
    Java中一直有final说明符,但C++98中没有,我理解这是C++11向Java“取经”的特征。

    override是显式说明此函数为重载基类中的虚函数,避免因写错函数名或参数或说明符(如少了const)导致误增了一个新函数。
    另外,因为virtual关键字在派生类中可以省略也常常被省略,读者不知道当前函数是重载还是新函数,override关键字可以起到帮助阅读的作用。
    https://zh.cppreference.com/w/cpp/language/override
    final和override可以作为普通的变量名,只有在函数和类名后才作为说明符,这是为了兼容存量代码。

    模板函数的默认模板参数

    C++98支持模板类有默认模板参数,但不支持模板函数有模板参数,C++11把这个补上了。

    void DefParm(int m=3) {}  // 都支持
    
    template <typename T = int>  // 都支持
    class DefClass {};
    
    template <typename T = int>  // C++98不支持
    void DefTempParm() {};
    

    由此引发的模板函数默认参数的规则,不展开了

    相关文章

      网友评论

        本文标题:[C++11阅读][1-2-3]提高代码稳定性(中)

        本文链接:https://www.haomeiwen.com/subject/udyinhtx.html