【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

https://blog.csdn.net/TH_NUM/article/details/81206789?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-2

简单工厂模式

简单工厂模式可以说是大多数人接触到的第一个设计模式。资源请求者(客户)直接调用工厂类中的函数,工厂根据传入的参数返回不同的类给资源请求者。下面给出在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");
}

https://www.cnblogs.com/caiminfeng/p/5311934.html

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) \
{ \
    assert(0 && "abstract class"); \
    return NULL; \
} \
    __TYPE__ *pRet = new(std::nothrow) __TYPE__(); \
if (pRet) \
    { \
    return pRet; \
    } \
    else \
    { \
    delete pRet; \
    pRet = NULL; \
    return NULL; \
    } \
}


由于宏定义是在编译前的字符串替换,所以最好每句都加上“\”符号,然后有必要的话最外面加括号。

ok,一个小技巧,感觉比写virtual函数爽多了!~w_w~

原文链接:https://blog.csdn.net/qq_22984991/article/details/51520412

猜你喜欢

转载自blog.csdn.net/bandaoyu/article/details/107423063