C++编程进阶9(如何将构造函数和非成员函数虚化、无锁单例模式)

三十二、如何动态调用构造函数和非成员函数

构造函数一般都不是虚函数,而非成员函数也不能是虚函数,如何才能动态创建对象呢?整体做法就是将创建对象的过程封装在一个基类虚函数中,然后在不同的子类中重写基类的虚函数,用来创建出不同的子类对象

1、构造函数的虚化

class basetype
{
public:
	basetype(){cout<<__func__<<endl;}
	virtual ~basetype(){cout<<__func__<<endl;}
	virtual basetype *clone()=0;
};

class type1:public basetype
{
public:
	type1(){cout<<__func__<<endl;}
	~type1(){cout<<__func__<<endl;}
	virtual type1 *clone() {
		cout<<__func__<<endl;
		return new type1();
	}
};

class type2:public basetype
{
public:
	type2(){cout<<__func__<<endl;}
	~type2(){cout<<__func__<<endl;}
	virtual type2 *clone() {
		cout<<__func__<<endl;
		return new type2();
	}
};

void destroy(basetype *bp) {
	cout<<__func__<<endl;
	delete bp;
}

int main(int argc, char const *argv[])
{
	basetype *bp=new type1();
	basetype *bp2=bp->clone();
	cout<<"----------"<<endl;
	destroy(bp2);
	delete bp;
	return 0;
}

上述代码中的子类type1和type2中重写了基类中的clone函数,这样就可以达到动态调用的目的

这里涉及到这样的一个点:如果基类虚函数的返回类型是个基类的指针或引用,那么,当子类重新实现基类的虚函数时,子类对应的虚函数可以返回一个指向该基类的子类的指针或引用。这样可以准确地动态创建出不同子类的对象

 

2、非成员函数的虚化

非成员函数的虚化的基本思路就是非成员函数调用虚函数,C++会根据基类函数形参指针或引用的动态类型来进行动态调用

示例

class basetype
{
public:
	//...
	virtual ostream &print(ostream &os)=0;
};

class type1:public basetype
{
public:
	//...
	virtual ostream &print(ostream &os) {
		cout<<__func__<<"in type1"<<endl;
		return os;
	}
};

class type2:public basetype
{
public:
	//...
	virtual ostream &print(ostream &os) {
		cout<<__func__<<"in type2"<<endl;
		return os;
	}
};

ostream &operator<<(ostream &os, basetype *bp)
{
	return bp->print(os);
}

//...

int main(int argc, char const *argv[])
{
	basetype *bp=new type1();
	cout<<bp<<endl;
	delete bp;
	return 0;
}

 

三十三、无锁单例模式

class test
{
friend test &getinstance();
private:
	test(){}
public:
	~test(){}
	
};

test &getinstance()
{
	static test instance;
	return instance;
}

上述代码中有三个点:1、test的构造函数是private,可以压制对象的产生;2、全局函数getinstance是test的一个友元,所以,getinstance不受私有构造函数的约束,可以产生对象;3、getinstance中有一个 static test对象,意思是只有一个test对象会被产生出来。

函数拥有一个static 对象的意思是:此对象在函数第一次被调用时才产生并且只产生一次。如果该函数从未被调用,这个对象也就绝不会诞生。static对象在程序结束时,所占内存会被释放

test &getinstance()
{
	static test instance;
	return instance;
}

void *thread_func(void *)
{
	getinstance();
	return nullptr;
}

int main(int argc, char const *argv[])
{
	getinstance();
	pthread_t tid;
	pthread_create(&tid, nullptr, thread_func, nullptr);
	pthread_join(tid, nullptr);
	return 0;
}

可见,即使getinstance被调用两次,依然只有一个全局对象生成,所以,单例模式可以通过static实现无锁的单例模式

 

参考

《More Effective C++》

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值