保持C ++模块化而不在类之间传递函数

时间:2017-02-24 17:49:17

标签: c++ c++11 inheritance

我想保持我的代码模块化。目前我的代码设置将函数从子类传递给父类。但它根本不编译。现在我想要一起摆脱传递的功能,但要保持模块化的能力。

更新:我添加了有关我的代码正在执行的操作的更多信息。我仍然遗漏了我正在做的大部分事情。 Class Molecule正在优化Class Rates的多个实例。 Class Rates正在优化由Rates内的单个函数生成的多个值。

Class Data_Analysis {
    virtual double find_rms_A (vector<double>) = 0;
    virtual double find_rms_B (vector<double>) = 0;
    virtual double find_rms_C (vector<double>) = 0;
    double E (double (Data_Analysis::*fxn(vector<double>)) {
        // doing tons of stuff
        (this->*fxn)(vec);
        //Simplex is third party library that requires a function that 
        // takes vector<double> and outputs a double
        //http://www.codeguru.com/cpp/article.php/c17505/Simplex-Optimization-Algorithm-and-Implemetation-in-C-Programming.htm
        Simplex((this->*fxn)(vec)); 
    }
};

Class Molecule: Data_Analysis {
    virtual double find_rms_A (vector<double> ) {
        // using variables only declared in Molecule
        double rms = 0.0
        for ( int data_point_A = 0; data_point_A < num_data_point_A; data_point_A++) {
            Rates r(data_point_A);
            r.run_simulation_v1();
            rms += r.return_rate();
        }
        return rms;
    }

    virtual double find_rms_B (vector<double>) {
        // using variables only declared in Molecule
        double rms = 0.0
        for ( int data_point_B = 0; data_point_B < num_data_point_B; data_point_B++) {
            //do stuff
            rms += rate;
        }
        return rms;
    }
    void optimize_A () {
        // set variables for type of optimization A
        E(&Data_Analysis::find_rms_A);
    }
    void optimize_B () {
        // // set variables for type of optimization B
        E(&Data_Analysis::find_rms_B);
    }
};

Class Rates: Data_Analysis {
    virtual double find_rms_C (vector<double>) {
        // using variables only declared in Rates
        double rms = 0.0
        for ( int data_point_C = 0; data_point_C < num_data_point_C; data_point_C++) {
            // run simulation that is completely different than anything used in Molecule
            rms += rate;
        }
        return rms;
    }
    void optimize_C () {
        // set variables for type of optimization C
        E(&Data_Analysis::find_rms_C);
    }
};

我试图让传递函数工作的事情:

Virtual Function 1Virtual Function 2Virtual Function 3:&#34;无法将变量'r'声明为抽象类型'Child2'&#34;

Pointer Functions 1Pointer Functions 2:&#34;无法将'double(Child1 :: )(std :: vector)'转换为'Parent :: fxn {aka double()(std :: vector)}'在初始化&#34; (星号正在制作斜体字。)

所以,我想重新组织我的代码来绕过传递函数。但我不知道如何在不摆脱功能E&#39;并重复功能A-D中的代码(又称破坏模块化)。任何提示/建议?

2 个答案:

答案 0 :(得分:0)

如果要传递特定于子项的函数,请不要通过Parent中定义的虚函数执行此操作。杀死虚函数,并将你想要的子特定函数直接传递给E.使用std :: bind来包装Child1Child2 - ness,这样E就不关心函数了除了它的论点。

class Parent {
    double E (std::function<double (vector<double>)> fn) {
        // doing tons of stuff
        fn(vec);
    }
};

class Child1: public Parent {
    double A (vector<double>) {
        // using variables only declared in Child1
    }
    double B (vector<double>) {
        // using variables only declared in Child1
    }
    void F () {
        E(std::bind(&Child1::A, this, std::placeholders::_1));
        E(std::bind(&Child1::B, this, std::placeholders::_1));
    }
};

设计试金石是:如果在所有子类中实现虚函数没有意义,那么它可能不应该是...

您也可以使用lambda代替来电。

另外,你确定要按值传递向量吗?您可能希望通过const引用传递。

答案 1 :(得分:0)

至少乍一看,似乎你的问题来自于代码不够模块化。

在我看来,你将两个独立的东西组合成一个单独的类。你有一些东西可以进行某种整体计算,可以进行单独的计算。

在我看来,这种情况下你需要更多的东西:

// Each derived object only (apparently) needs two functions, so that's
// what we'll define as the interface:
struct base { 
    // equivalent to child1::A and B, and to child2::C and D:
    virtual double A(std::vector<double> const &) = 0;
    virtual double B(std::vector<double> const &) = 0;
};

// Then a class for the overall computation, using (a pointer to) one of the 
// preceding:    
struct compute {
    // equivalent to Parent::E().
    double E (base *b) {
        b->A(vec);
        Simplex(b->A(vec));
        b->B(vec);
        Simplex(b->B(vec));
    }    
};

struct child1 : public base {
    // Now each child provides two functions:
    double A(std::vector<double> const &p) { 
        // do child1 computation A
    }
    double B(std::vector<double> const &p) {
        // do child1 computation B
    }

    void F(compute *c) { 
        c->E(this);
    }        
};

struct child2 : public base {
    double A(std::vector<double> const &p) { 
        // do child2 computation A
    }
    double B(std::vector<double> const &p) {
        // do child2 computation B
    }
    void G(compute *c) { 
        c->E(this);
    }    
};

可以说,child1::F()child2::G()可能真的应该是基类中的单个函数,因为它们基本上都是相同的。

如果你有一个指向child1child2个对象的指针集合(所以直到运行时你才知道特定指针是否会引用child1或一个child2),你想对所有这些操作执行相同的操作,前面的设计是有意义的。

另一方面,如果您在编译时知道某个特定实例是child1还是child2,您可以将child1child2作为模板参数,避免虚函数的开销:

// The class contained only a single function, so it can be just a function:
template <class F>
double compute(F const &f) {
    f.A(vec);
    Simplex(f.A(vec));
    f.B(vec);
    Simplex(f.B(vec));
}

class child1 { // no longer needs a common base class
    double A(std::vector<double> const &);
    double B(std::vector<double> const &);
    void F() { compute(this); }
};

class child2 { // no longer needs a common base class
    double A(std::vector<double> const &);
    double B(std::vector<double> const &);
    void G() { compute(this); } 
};