C++11 -- final与override关键字和类的新功能

目录

final与override关键字

final

override

类的新功能

默认成员函数

类成员变量初始化

default关键字

delete关键字


final与override关键字

final

final:修饰虚函数,表示该虚函数不能再被重写

//基类
class Person {
public:
	//被final修饰,该虚函数不能再被重写
	virtual void BuyTicket() final
	{ 
		cout << "Person-买票-全价" << endl; 
	}
};
//派生类
class Student : public Person {
public:
	//派生类的虚函数重写了父类的虚函数
	virtual void BuyTicket() { cout << "Student-买票-半价" << endl; } // 编译不通过
};

 上面代码会直接编译不过

final 关键字也可用于实现一个不能被继承的类  

如何实现一个不能被继承的类??

  1. 把构造函数进行私有,这是 C++98 的做法
  2.  类定义时 加 final 关键字,这是 C++11的做法
//基类使用 final 修饰
class A final
{};
//派生类无法进行继承基类
class B : public A
{}

override

override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错


//基类
class Person {
public:
	//基类的虚函数
	virtual void BuyTicket() { cout << "Person-买票-全价" << endl; }
};
//派生类
class Student : public Person {
public:
	//派生类完成了虚函数的重写,编译通过
	virtual void BuyTicket()override
	{ 
		cout << "Student-买票-半价" << endl; 
	}
};
//派生类
class Soldier : public Person
{
public:
	//派生类没有完成虚函数的重写,编译报错
	virtual void BuyTicket(int n)override
	{ 
		cout << "Soldier-优先-买票" << endl;
	}
};

类的新功能

默认成员函数

在C++11之前,一个类中有如下六个默认成员函数

  • 1. 构造函数
  • 2. 析构函数
  • 3. 拷贝构造函数
  • 4. 拷贝赋值重载
  • 5. 取地址重载
  • 6. const 取地址重载

最重要的是前4个,后两个用处不大。默认成员函数就是我们不写编译器会生成一个默认的

C++11 新增了两个:移动构造函数和移动赋值运算符重载

默认移动构造的生成条件

如果你没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个。那么编译器会自动生成一个默认移动构造。

移动构造的默认行为: 

默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,如果实现了就调用移动构造,没有实现就调用拷贝构造 

默认移动赋值的生成条件

如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个,那么编译器会自动生成一个默认移动赋值。

移动赋值的默认行为:  

默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造完全类似)

注意:如果提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值

类成员变量初始化

C++11允许在类定义时给成员变量初始缺省值,默认生成构造函数会使用这些缺省值初始化

class Person
{
public:
	//...
private:
	//非静态成员变量,可以在成员声明时给缺省值
	string _name = "张三"; //缺省值
	int _age = 22;         //缺省值
 
	static int _n; //静态成员变量不能给缺省值
};

注意:这里不是初始化,给的的值是缺省值

default关键字

default关键字的作用是:强制生成默认函数

C++11可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数,但是因为一些原因这个函数没有默认生成。比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以使用default关键字显示指定移动构造生成

使用:在需要强制生成默认函数的声明后面加上 =default 即可
 


class Person
{
public:
	//构造函数
	Person(const char* name = "", int age = 0)
		:_name(name)
		, _age(age)
	{}
	//拷贝构造
	Person(const Person& p)
	 :_name(p._name)
	 ,_age(p._age)
	{}
	//移动构造
	Person(Person&& p) = default;
private:
	fy::string _name;
	int _age;
};
 
int main()
{
	Person s1;
	Person s2 = s1;
	Person s3 = std::move(s1);
	return 0;
}

使用了 default关键字后默认的移动构造可以生成,即便实现了拷贝构造函数

delete关键字

delete关键字的作用是:禁止生成默认函数 

使用:在需要禁止生成默认函数的声明后面加上 =delete 即可 

如果能想要限制某些默认函数的生成:

在C++98中,是该函数设置成private,并且只用声明不用定义,这样只要其他人想要调用就会报错。
在C++11中更简单,只需在该函数声明加上 =delete 即可,该语法指示编译器不生成对应函数的默认版本,称 =delete 修饰的函数为删除
 

要让一个类不能被拷贝,可以用 =delete 修饰将该类的拷贝构造和赋值重载

class A
{
public:
	A()
	{}
private:
	//强制不允许生成
	A(const A&) = delete;
	A& operator=(const A&) = delete;
};
 
int main()
{
	A a1;
	A a2(a1);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值