我希望能够检查某个Derived
类型的对象上是否存在某个条件,该对象在本地上下文中仅通过其Base
类型已知。
要检查的条件需要Derived
类型的特定知识,但是我试图实现一个间接级别,允许在只知道基类的上下文中进行检查。
实现此目的的一种可能方法是将检查所需的信息封装在仿函数(或lambda)中,并将其发送到需要执行检查的位置。
定义类
class Base {
//...
public:
using Condition = std::function<bool(const Base*)>;
bool check(const Condition&);
}
class DerivedA : public Base {
//...
public:
int index() const { return index;}
private:
int index;
}
class DerivedB : public Base {
//...
public:
std::string name() const { return name;}
private:
std::string name;
}
并假设我们有一个Derived
- 感知上下文,我可以在lambda函数中封装Derived
特定条件。然后,我们可以将Condition
仿函数分派到需要它的上下文中:
//context where DerivedA and DerivedB are known
int idx = 1;
auto derivedCondition = [idx](const Base* obj) {
DerivedA* derivedObj = dynamic_cast<const DerivedA*>(obj);
if (derivedObj)
return (derivedObj->index() == idx);
return false;
};
std:string str = "Peter";
auto derivedCondition = [str](const Base* obj) {
DerivedB* derivedObj = dynamic_cast<const DerivedB*>(obj);
if (derivedObj)
return (derivedObj->name() == str);
return false;
};
// dispatch condition to an external context where it will be used, this context is not aware of Derived
useConditionElsewhere(derivedCondition);
与
void useConditionElsewhere(Condition condition) {
//context where only base class is known
Base* baseObj;
//... suppose baseObj is created from a factory class that returns a random subclass
// baseObj can be a DerivedA, DerivedB or none of them
bool checked = baseObj->check(condition);
//..
}
以上实现了我的需要。
我的问题是:是否可以在不投标的情况下执行此操作?
答案 0 :(得分:2)
假设您要创建一个ConditionChecker类,并为您需要检查的各种类型重载检查函数: -
class ConditionChecker
{
public:
bool checkCondition(DerivedA& toBeChecked)
{
//some checking code that knows about DerivedA objects
}
bool checkCondition(DerivedB& toBeChecked)
{
//some checking code that knows about DerivedB objects
}
};
如果现有的Base类有一个名为check的虚函数,它接受一个ConditionChecker对象: -
virtual bool check(ConditionChecker& checker) = 0;
然后这可以在派生类中实现为
bool check(ConditionChecker& checker)
{
return checker.checkCondition(*this);// calls the correct overload
}
答案 1 :(得分:1)
这里似乎有double dispatch的案例。本质上,您的检查条件调用依赖于两种动态类型:Base的派生类型和条件本身的类型(尽管您将示例编写为示例中的std :: function,在这种情况下,它在很多方面都是等效的)。在C ++中,没有本机双分派,这种问题通常通过使用两个继承层次结构和两个调用来解决。这正是@ROX给出的解决方案。他的ConditionChecker可以成为一个带有虚拟checkConditionCalls的基类,以便检查各种条件。每个派生的条件类将实现多个checkCondition函数,一个用于DerivedA,另一个用于DerivedB(以及您选择添加的任何其他函数) - 因此它们将具有要检查的条件和派生类型的特定知识。
答案 2 :(得分:0)
很难理解你想要什么。但这里是使用虚方法重写的代码。我希望它会迫使你产生正确的答案。
class Base {
//...
public:
virtual bool check(int idx) override { return idx == index();}
}
class Derived : public Base {
//...
public:
int index() const { return index;}
virtual bool check(int idx) { return false; }
private:
int index;
}
void useConditionElsewhere(int idx) {
//context where only base class is known
Base* baseObj;
//...
bool checked = baseObj->check(idx);
//..
}