将通用子类上的检查条件分派给仅知道基类的上下文

时间:2016-04-28 13:32:28

标签: c++ oop c++11

我希望能够检查某个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);
    //..
 }

以上实现了我的需要。

我的问题是:是否可以在不投标的情况下执行此操作

3 个答案:

答案 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);
    //..
 }