三十二、如何动态调用构造函数和非成员函数
构造函数一般都不是虚函数,而非成员函数也不能是虚函数,如何才能动态创建对象呢?整体做法就是将创建对象的过程封装在一个基类虚函数中,然后在不同的子类中重写基类的虚函数,用来创建出不同的子类对象
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++》
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出