C++ noncopyable原理及实现

C++ noncopyable原理及实现

默认构造函数、拷贝控制成员以及它们的合成版本

默认构造函数

不含参数或者只含一个参数并且参数有默认值的构造函数。
如果类没有定义任何构造函数,编译器会为其合成一个无参默认构造函数,也就是合成的默认构造函数。
如果类定义了构造函数,编译器不会为其合成默认构造函数,也就不能执行默认初始化了,如:

class A {
	int val;
	A(int v):val(v) {}
};

A a;         //编译出错,没有默认构造函数

可以指定编译器合成一个默认构造函数,用default关键字。(只能对具有合成版本的成员函数使用此关键字,如默认构造函数和拷贝控制成员)

class A {
	int val;
	A(int v):val(v) {}
	A() = default;
};

A a;   //编译通过
合成的拷贝控制成员
  1. 合成的拷贝控制成员包括拷贝构造函数和拷贝赋值运算符。
  2. 如果类没有定义拷贝构造函数,编译器会为其定义一个,即使类定义了构造函数,编译器也会为其合成一个拷贝构造函数。
  3. 如果类没有定义拷贝赋值运算,编译器会为其定义一个,也就是合成的拷贝赋值运算符。
  4. 可以用关键字default显示要求编译器合成一个拷贝控制成员。

访问控制和继承

访问控制
  1. 类的私有成员只能有本类的其他成员和友元来访问。
  2. 类的受保护成员不可以由类的用户访问,可以由派生类的成员和友元访问。
  3. 派生类的成员和友元只能通过派生类对象访问基类的受保护成员,不能直接访问基类对象的受保护成员。

如:

class Base {
protected:
	int val;
};

class Derived:public Base{
friend void f1(Base&);
friend void f2(Derived&);
};

void f1(Base &b) {b.val = 10;}   //错误,不能通过基类对象访问
void f2(Derived &d) {d.val = 10;}  //正确,可以通过派生类对象访问基类部分的protected

公有、私有和受保护继承

某个类对继承而来的成员的访问权限受两个因素影响:
一是基类中该成员的访问说明符;
二是派生类的派生列表中的访问说明符。

派生列表中的访问控制说明符对派生类的成员和友元能否访问其直接基类的成员没有影响,对基类成员访问只与基类中访问说明符有关。

class Base {
public:
	void pub_mem();
protected:
	int prot_mem;
private:
	int priv_mem;
};

struct Pub_Derv : public Base {
	int f() { return prot_mem; }  //正确,可以访问
	int g() { return priv_mem; }  //错误,不可访问私有成员
};

struct Priv_Derv : private Base {
	int f() { return prot_mem; }  //正确,不影响访问
};

int main(){
	Pub_Derv pub;
	Priv_Derv priv;
	pub.pub_mem();   //正确,public继承 用户(包括派生类的派生类)可以直接访问类的基类部分的共有成员
	priv.pub_mem();  //错误,private继承 用户不能访问类的基类部分的任何成员
}

noncopyable原理及实现

class noncopyable的基本思想是把构造函数和析构函数设置protected权限,这样子类可以调用,但是外面的类不能调用,那么当子类需要定义构造函数的时候不至于通不过编译。但是最关键的是noncopyable把拷贝构造函数和拷贝赋值函数做成了private的,继承自noncopyable的类在执行拷贝操作时会调用基类的拷贝操作,但是基类的拷贝操作是private的,因此无法调用,引发编译错误。

class noncopyable
{
 public:
  noncopyable(const noncopyable&) = delete;//拷贝构造禁用
  void operator=(const noncopyable&) = delete;//赋值禁用

 protected:
  noncopyable() = default;
  ~noncopyable() = default;
};

noncopyable有啥优势

​ 对象是否可复制,与他是否使用RAII技巧无关,却与它 本身是值语义还是引用语义相关

值语义:关心这个对象表示的值。在复制的时候,类似使用普通的int。使用的是其值。复制前后的对象没有关系。

引用语义:关心对象本身,复制一个具有引用语义的对象通常是没有意义的。例如复制一个线程,理论上需要完全创建一个相同的线程才行,所以不允许复制。

​ 如果不清楚某个类是否应该复制,默认可以写成不可复制,必要时修改为可复制,通常这是一个不错的做法。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值