非静态成员的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() {};
由此引发的模板函数默认参数的规则,不展开了
网友评论