【C++】⼯⼚函数和⼯⼚模式⽬录
⼯⼚函数
c++ define 定义⼯⼚函数,其中define函数名使⽤##连接
# include<stdio.h>
# include <stdlib.h> //atoi
# include <string.h> //strlen
# include <stdint.h> //uint64_t
#include<iostream>
#include<memory>
using namespace std;
template <class T>
int DoAllreduce(T tensor, T output) {
return tensor+output;
}
#define ALLREDUCE(torch_Tensor, THTensor) \
extern "C" int horovod_torch_allreduce_async_##torch_Tensor( \
THTensor tensor, THTensor output) { \
printf("this is all reduce!\n");\
DoAllreduce(1,1);\
return 0; \
}
ALLREDUCE(torch_bbyte,int)
ALLREDUCE(torch_bbyte2,int)
int main(){
horovod_torch_allreduce_async_torch_bbyte(1,1);
horovod_torch_allreduce_async_torch_bbyte2(1,1);
return 0;
}
输出:
this is a construc function!
the sum of A is 3
share_ptr:00871244
请按任意键继续. . .
区别#与##
# 是把参数字符串化,## 是将两个参数连为⼀个整体。
#include <iostream>
#include <cstdlib>
// 测试不带 # 号的效果
#define NO_NUMBER_SIGN(x) x
// 测试⼀个 # 号的效果
#define SINGLE_NUMBER_SIGN(x) #x
// 测试两个 # 号的效果
#define DOUBLE_NUMBER_SIGN(x, y) x##y
int main()
{
// 测试不带 # 号的效果:hello 不加双引号报错(error C2065: “hello”: 未声明的标识符)
std::cout << NO_NUMBER_SIGN("hello") << std::endl;
// 测试⼀个 # 号的效果:world 加不加双引号都可以,因为 # 将其字符串化
std::cout << SINGLE_NUMBER_SIGN(world) << std::endl;
// 测试两个 # 号的效果:连接两个对象
std::cout << DOUBLE_NUMBER_SIGN("hello", "world") << std::endl;
system("pause");
return 0;
}
输出:
hello
world
helloworld
简单⼯⼚模式可以说是⼤多数⼈接触到的第⼀个设计模式。资源请求者(客户)直接调⽤⼯⼚类中的函数,⼯⼚根据传⼊的参数返回不同的类给资源请求者。下⾯给出在C++中使⽤简单⼯⼚模式的⼀个demo,采⽤了auto_ptr智能指针管理类资源。
值得注意的是抽象类Product中的析构函数必须为虚函数。《Effective C++》条款07:为多态基类声明virtual析构函数。
采⽤auto_ptr也符合《Effective C++》条款13:以对象管理资源、条款18:让接⼝容易被正确使⽤,不易被误⽤。
#include <iostream>
using namespace std;
enum ProductType{ TypeA, TypeB, TypeC };
class Product{
public:
virtual void show() = 0;
virtual ~Product(){};//virtual destructor
};
class ProductA :public Product{
public:
void show(){
cout << "A" << endl;
}
ProductA(){
cout << "constructing A" << endl;
}
~ProductA(){
cout << "destructing A" << endl;
}
};
};
class ProductB :public Product{
public:
void show(){
cout << "B" << endl;
}
ProductB(){
cout << "constructing B" << endl;
}
~ProductB(){
cout << "destructing B" << endl;
}
};
class ProductC :public Product{
public:
void show(){
cout << "C" << endl;
}
ProductC(){
cout << "constructing C" << endl;
}
~ProductC(){
cout << "destructing C" << endl;
}
};
class ProductFactory{
public:
static auto_ptr<Product> createProduct(ProductType type){
switch (type){
case TypeA: return auto_ptr<Product>(new ProductA());
case TypeB: return auto_ptr<Product>(new ProductB());
case TypeC: return auto_ptr<Product>(new ProductC());
default: return auto_ptr<Product>(NULL);
}
}
};
int main()
{
{
auto_ptr<Product> proA = ProductFactory::createProduct(TypeA);
auto_ptr<Product> proB = ProductFactory::createProduct(TypeB);
auto_ptr<Product> proC = ProductFactory::createProduct(TypeC);
proA->show();
proB->show();
proC->show();
}
system("pause");
}
c++⼩技巧,宏定义⼯⼚函数
这⼏天在写鱼类抽象的时候,发现原来使⽤⽗类指针创建,替换,转化⼦类对象的⽅法原来叫⼯⼚模式,以前常常⽤这种⽅法,终于发现原来是有学名的。(●’◡’●)
这⾥介绍⼀种使⽤宏定义函数来创建⼯⼚函数的⽅法,借鉴了cocos的宏。
1、⾸先,我们要避免创建⼀个不能实例化的抽象⽗类,除去⽤RTTI,使⽤类id,我们还可以⽤如下⽅案:
template <typename T>
struct IsAbstract
{
typedef char SmallType;
typedef int LargeType;
template <typename U>
static char Test(U(*)[1]);
template <typename U>
static int Test(...);
const static bool Result = sizeof(Test<T>(NULL)) == sizeof(LargeType);
};
这是笔者在知乎上到的⼀个例⼦,也就是⽤了c++数组对象不能是抽象类这⼀点,⾃动匹配重载函数的时候会匹配到使⽤任何参数的Test(…),然后⾃然就返回⼀个char的长度。
然后我们来看宏定义函数,有两个,⼀个是添加create函数,⼀个是⽤于⼯⼚模式创建类:
#define CREATE_FISH(__FISHTYPE__) ([](){ return __FISHTYPE__::create();})
//检查是否是完整类(避免抽象类被实现从⽽导致错误),然后使⽤⼯⼚函数创建类
#define ADD_CREATE(__TYPE__) \
static __TYPE__* create() \
{ \
if (IsAbstract<__TYPE__>::Result) \
enum函数{ \
assert(0 && "abstract class"); \
return NULL; \
} \
__TYPE__ *pRet = new(std::nothrow) __TYPE__(); \
if (pRet) \
{ \
return pRet; \
} \
else \
{ \
delete pRet; \
pRet = NULL; \
return NULL; \
} \
}
由于宏定义是在编译前的字符串替换,所以最好每句都加上“\”符号,然后有必要的话最外⾯加括号。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论