我有一些功能需要应用于3个不同变量(x
,y
,z
)的不同域。通常,每个函数仅将变量之一作为输入。例如:
float myFunction(float val) { return val * 3.14159; }
这些函数可以是简单的常数乘法,插值,导数等。我想拥有一个vector
,其中包含在不同域中定义的函数。例如,所有x
函数都在std::vector<…> xFunctions
,std::vector<…> yFunctions
等中。
现在,我需要增加一个函数的功能,以将所有三个变量用作输入,但我想将它们保留在vector
s中。
这是一个例子
#include <limits>
#include <vector>
#include <memory>
#include <iostream>
class Model {
public:
Model(float b1 = 0.0, float b2 = std::numeric_limits<float>::infinity())
: lowerBound(b1), upperBound(b2) {}
virtual float Function(float inp) { return 0.0; }
float GetUpperBound() const { return upperBound; }
float GetLowerBound() const { return lowerBound; }
protected:
float lowerBound, upperBound;
};
class ConstantModel : public Model {
public:
ConstantModel(float b1 = 0.0,
float b2 = std::numeric_limits<float>::infinity(),
float f = 0.0)
: Model(b1, b2), factor(f) {}
float Function(float inp) { return factor; }
private:
float factor;
};
class LinearModel : public Model {
private:
float interpFactor1, interpFactor2;
float interpTerm;
public:
LinearModel(float b1 = 0.0, float b2 = std::numeric_limits<float>::infinity(),
float f1 = 0.0, float f2 = 0.0)
: Model(b1, b2), interpFactor1(f1), interpFactor2(f2) {
interpTerm = (interpFactor1 - interpFactor1) / (upperBound - lowerBound);
}
float Function(float inp) {
return interpFactor1 + (inp - lowerBound) * interpTerm;
}
};
class MultipleInputs : public Model {
private:
float factor;
public:
MultipleInputs(float b1 = 0.0,
float b2 = std::numeric_limits<float>::infinity(),
float f1 = 0.0)
: Model(b1, b2), factor(f1) {}
float Function(float inpX, float inpY, float inpZ) {
return factor * (inpX + inpY + inpZ);
}
};
int main() {
// In practice I have xModels, yModels, zModels
std::vector<std::unique_ptr<Model>> xModels;
xModels.emplace_back(new ConstantModel(0.0, 1.0, 3.14159));
xModels.emplace_back(new LinearModel(1.0, 2.0, 1.0, 2.0));
xModels.emplace_back(new MultipleInputs(3.0, 4.0, -1.0));
float xValue;
float yValue(1.0), zValue(2.0);
std::cin >> xValue;
// Find the applicable function to use
std::size_t i = 0;
while (xModels[i]->GetUpperBound() < xValue) {
++i;
}
float result = xModels[i]->Function(xValue);
std::cout << result << std::endl;
;
return 0;
}
如果我输入0.5
,则结果为3.14159
。如果输入1.5
,则结果为1
。如果输入3.5
,我希望答案为(3.5 + 1.0 + 2.0) * -1.0 = -6.5
。但是,我得到了0
,因为调用了函数Model::Function
。这很合理,因为我只给出1个输入。如果我给出3个输入,则会得到预期的编译器错误“函数不带有3个参数”。
我开始使用decltype
和运行时类型标识,但这让我觉得我做错了。使继承的类成员函数比基类接受更多输入的正确方法是什么?
更新
我修改了基类以使其具有重载的Function(float, float, float)
,然后使用typeid.hash_code()
确定是否需要使用这样的1或3输入函数。
#include <limits>
#include <vector>
#include <memory>
#include <iostream>
#include <typeinfo>
class Model {
public:
Model(float b1 = 0.0, float b2 = std::numeric_limits<float>::infinity()) :
lowerBound(b1), upperBound(b2) {}
virtual float Function(float inp) { return 0.0; }
virtual float Function(float i1, float i2, float i3) { return 0.0; }
float GetUpperBound() const { return upperBound; }
float GetLowerBound() const { return lowerBound; }
protected:
float lowerBound, upperBound;
};
class ConstantModel : public Model {
public:
ConstantModel(float b1 = 0.0, float b2 = std::numeric_limits<float>::infinity(), float f = 0.0) :
Model(b1, b2), factor(f) {}
float Function(float inp) { return factor; }
private:
float factor;
};
class LinearModel : public Model {
private:
float interpFactor1, interpFactor2;
float interpTerm;
public:
LinearModel(float b1 = 0.0, float b2 = std::numeric_limits<float>::infinity(), float f1 = 0.0, float f2 = 0.0) :
Model(b1, b2), interpFactor1(f1), interpFactor2(f2) {
interpTerm = (interpFactor1 - interpFactor1) / (upperBound - lowerBound);
}
float Function(float inp) { return interpFactor1 + (inp - lowerBound) * interpTerm; }
};
class MultipleInputs : public Model {
private:
float factor;
public:
MultipleInputs(float b1 = 0.0, float b2 = std::numeric_limits<float>::infinity(), float f1 = 0.0) :
Model(b1, b2), factor(f1) {}
float Function(float inpX, float inpY, float inpZ) { return factor * (inpX + inpY + inpZ); }
};
int main() {
// In practice I have xModels, yModels, zModels
std::vector<std::unique_ptr<Model> > xModels;
std::vector<std::size_t> tags;
tags.emplace_back(typeid(Model).hash_code());
tags.emplace_back(typeid(ConstantModel).hash_code());
tags.emplace_back(typeid(LinearModel).hash_code());
tags.emplace_back(typeid(MultipleInputs).hash_code());
for (auto i : tags) {
std::cout << i << std::endl;
}
xModels.emplace_back(new ConstantModel(0.0, 1.0, 3.14159));
xModels.emplace_back(new LinearModel(1.0, 2.0, 1.0, 2.0));
xModels.emplace_back(new MultipleInputs(3.0, 4.0, -1.0));
float xValue;
float yValue(1.0), zValue(2.0);
std::cin >> xValue;
// Find the applicable function to use
std::size_t i = 0;
while (xModels[i]->GetUpperBound() < xValue) {
++i;
}
float result;
if (typeid(*xModels[i]).hash_code() == tags[3]) {
result = xModels[i]->Function(xValue, yValue, zValue);
}
else {
float result = xModels[i]->Function(xValue);
}
std::cout << result << std::endl;;
return 0;
}
从某种意义上说,这是可行的,我可以在需要时获得3输入版本,但是感觉有更好的方法来实现。
答案 0 :(得分:1)
让继承的类成员函数比基类接受更多输入的正确方法是什么?
不能用不同的签名重新定义虚拟函数,并且派生类必须根据基类的规范实现所有虚拟函数。如果您不能确保这一点,则说明您的设计存在问题,您想对其进行修改。
除了原始的继承函数之外,派生类还可以定义一个新的,不相关的函数。如果签名不同,则两个函数可能具有相同的名称,从而导致函数重载。