Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用多组方法实现设计类[c+;+;]_C++_Design Patterns - Fatal编程技术网

C++ 使用多组方法实现设计类[c+;+;]

C++ 使用多组方法实现设计类[c+;+;],c++,design-patterns,C++,Design Patterns,我正在处理一个现有项目,该项目有一个类,我需要一个备用成员函数定义。我不想修改现有的成员函数或它们的签名,只想修改一个备用定义,它必须在运行时根据某个xml文件进行选择(编译时标志不是首选)。 我是C++新手,所以这可能是个愚蠢的问题。 请建议设计指南,这样我就不必更改和测试现有的代码库,只需插入我的实现 示例 class ABC{ public: int operate(int, int); } //Assume below method to be existing implementa

我正在处理一个现有项目,该项目有一个类,我需要一个备用成员函数定义。我不想修改现有的成员函数或它们的签名,只想修改一个备用定义,它必须在运行时根据某个xml文件进行选择(编译时标志不是首选)。 我是C++新手,所以这可能是个愚蠢的问题。 请建议设计指南,这样我就不必更改和测试现有的代码库,只需插入我的实现

示例

class ABC{
public:
int operate(int, int);
}  
//Assume below method to be existing implementation
ABC::operate(int op1, int op2)
{
   return op1+ op2; //add
}

//Alternate desired implementation
ABC::operate(int op1, int op2)
{
   return op1 * op2; //multiply 
}
理想情况下,我希望上面是运行时选择,但如果这是唯一的方法,则可能会落在编译时。

请注意这个关于名称隐藏在继承中的线程

当派生类使用与基类中相同的名称实现非虚拟方法时,基类中的方法将隐藏,并且只有派生方法可以通过静态类型派生的对象使用

我给你的建议是实施类似于

class ABC{
public:
    int operate(int, int);
};  
//Assume below method to be existing implementation
ABC::operate(int op1, int op2)
{
    return op1+ op2; //add
}  
现在,对于您的扩展功能,从ABC派生(旁注:继承或组合是另一个讨论,请在google上阅读)

现在,无论您在哪里需要新功能,都可以将调用对象的静态类型更改为
派生
,然后将调用派生的
操作


如果可以将ABC的
operate
签名更改为
虚拟int-operate(int,int),则更符合逻辑的解决方案是可能的
,则可能发生polimorphism,通过任何地方的引用类型访问
operate
将调用属于调用对象的动态类型的
operate

因此,您只需将对象实例化为
派生
类型,而不是
ABC


请注意,如果操作是静态的,虚拟方法的使用是不可能的,这里不清楚是否是静态的。

我正在准备答案,但Gulzar同时回答了(他的答案结束)

你需要的是C++中的一个基本概念/机制,叫做“强>动态绑定< /强>(也许你在你的帖子是1个月的时候同时学习了)< /P>

#包括
#包括
使用名称空间std;
类ABC_基
{
公众:
//纯虚成员函数
//强制有效创建
//子类中的函数
虚拟整数运算(整数,整数)=0;
//将派生虚拟xtor作为基础
虚拟~ABC_Base(){}
};
ABC_M1类:公共ABC_基地
{
int运算(inta,intb){返回a+b;}
};
ABC_M2类:公共ABC_基地
{
int运算(inta,intb){返回a*b;}
};
ABC_Base*创建ABC(字符串xml_文件名)
{
int标准=0;
//nullptr至少需要c++11选项
ABC_Base*ptr=nullptr;
//读取xml文件并更新标准
//请参阅其他帖子
//标准=。。。
开关(标准)
{
案例0:
ptr=新的ABC_M1();
打破
案例1:
ptr=新的ABC_M2();
打破
违约:
打破
}
返回ptr;
}
int main()
{
ABC_Base*ptr=createABC(“My_Config.xml”);
if(nullptr!=ptr)
{

无法操作(3,4)您已经尝试过一些东西了吗?欢迎编写一个小草稿并更具体一些。选择编译时xml文件究竟是什么意思?您希望如何在编译时读取xml文件?这完全取决于您使用的构建系统。例如,使用makefiles,这是可行的。使用Visual Studio IDE,我不知道这是一个简单的方法。因为这不能在C++代码中完成,所以必须在编译器之外完成,就像一个脚本,在编译之前读取XML,并通过将编译宏插入到VS项目文件中来改变编译、FE。但是我想知道是否有任何这样的解决方案有意义的。<代码>如果< /COD>和
switch
语句是如何根据某些运行时条件选择要执行的代码分支。您还可以查看vtable和vptr的概念,了解动态绑定在内部的工作方式
class Derived : public ABC{
     operate(int op1, int op2){
          return op1 * op2; //multiply 
     }
}
    #include <iostream>
    #include <cstddef>

    using namespace std;


    class ABC_Base
    {
        public:
            //pure virtual member function
            //compelling effective creation of the
            //function in the daughter classes
            virtual int operate(int,int) = 0;
            //virtual xtor as base will be derived
            virtual ~ABC_Base() {}
    };

    class ABC_M1 : public ABC_Base
    {
        int operate (int a, int b ) {return a+b; }
    };

    class ABC_M2 : public ABC_Base
    {
        int operate (int a, int b ) {return a*b; }
    };

    ABC_Base * createABC(string xml_filename)
    {
        int criterion = 0;

        // nullptr need at least c++11 option
        ABC_Base * ptr = nullptr;

        //read xml file and update criterion
        //see other post to do that
        //criterion = ...

        switch(criterion)
        {
            case 0:
                ptr = new ABC_M1();
                break;
            case 1:
                ptr = new ABC_M2();
                break;

            default:
                break;
        }
        return ptr;
    }


    int main()
    {
        ABC_Base * ptr = createABC("My_Config.xml");

        if (nullptr != ptr)
        {
            cout << ptr->operate(3,4) << endl;
        }

        // If you absolutely want / have to use plain old pointers
        // do not forget to release things
        // works even if ptr is null, so unconditional delete
        delete(ptr);

        return 0;
    }