我想保持我的代码模块化。目前我的代码设置将函数从子类传递给父类。但它根本不编译。现在我想要一起摆脱传递的功能,但要保持模块化的能力。
更新:我添加了有关我的代码正在执行的操作的更多信息。我仍然遗漏了我正在做的大部分事情。 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 1,Virtual Function 2,Virtual Function 3:&#34;无法将变量'r'声明为抽象类型'Child2'&#34;
Pointer Functions 1,Pointer Functions 2:&#34;无法将'double(Child1 :: )(std :: vector)'转换为'Parent :: fxn {aka double()(std :: vector)}'在初始化&#34; (星号正在制作斜体字。)
所以,我想重新组织我的代码来绕过传递函数。但我不知道如何在不摆脱功能E&#39;并重复功能A-D中的代码(又称破坏模块化)。任何提示/建议?
答案 0 :(得分:0)
如果要传递特定于子项的函数,请不要通过Parent
中定义的虚函数执行此操作。杀死虚函数,并将你想要的子特定函数直接传递给E.使用std :: bind来包装Child1
或Child2
- 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()
可能真的应该是基类中的单个函数,因为它们基本上都是相同的。
如果你有一个指向child1
或child2
个对象的指针集合(所以直到运行时你才知道特定指针是否会引用child1
或一个child2
),你想对所有这些操作执行相同的操作,前面的设计是有意义的。
另一方面,如果您在编译时知道某个特定实例是child1
还是child2
,您可以将child1
或child2
作为模板参数,避免虚函数的开销:
// 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); }
};