C ++: binding to base class

EDIT:

The following code container::pushtakes an object of type Tthat is inferred from baseas an argument and stores a pointer to a method in a vector bool T::test().

container::callcausing each of the methods stored in the context of a Member of the object p, which has a type base, notT . It works until the called method refers to some element outside base, and if test()not declared virtual.

I know that this is ugly and may not be entirely correct.

How can I do the same better?

#include <iostream>
#include <tr1/functional>
#include <vector>

class base {
   public:
   base(int v) : x(v)
   {}
   bool test() const { // this is NOT called
      return false;
   }

   protected:
   int x;
};

class derived : public base {
   public:
   bool test() const { // this is called instead
      return (x == 42);
   }
};

class container {
   public:
   container() : p(42)
   {}
   template<typename T>
   void push(const T&) {
      vec.push_back((bool (base::*)() const) &T::test);
   }
   void call() {
      std::vector<bool (base::*)() const>::iterator i;
      for(i = vec.begin(); i != vec.end(); ++i) {
         if( (p .* (*i))() ) {
            std::cout << "ok\n";
         }
      }
   }

   private:
   std::vector<bool (base::*)() const> vec;
   base p;
};

int main(int argc, char* argv[]) {
   container c;
   c.push(derived());
   c.call();
   return 0;
}
+3
source share
3 answers

To the updated question:

- Undefined . , (), . , , .

+1

, boost-bind, - output:: test "b" "this". , "this" output:: test "" , . , vtable, , , , , .

, - , , . ?

[] : boost:: bind , - - . , , . boost ... , - boost:: bind ( , boost), , , .

+3

, , , , ( undefined) .

base::test derived::test , -, base::foo derived::bar. bar, derived, base, . derived base!!! undefined.

, , , this base derived , base. .

base::test virtual, : base, , base - , test .

derived::test ( base), ( vtable) .

, base::test , . :

class base {
public:
   virtual bool test() const;
};
class derived : public base {
public:
   virtual bool test() const; // <--- virtual is optional here, but informative
};
int main()
{
   derived d; // <--- the actual final type
   base & b = d;  // <--- optional
   if ( std::tr1::bind( &base::test, std::tr1::ref(b))() ) {
      // ...
   }
}

Note that there is no fill (castings are usually a hint of something strange, potentially dangerous hiding there), that the object is of a specific type, where you want this method to be called, and that the virtual sending mechanism ensures that even if bind matters base::testsince this method is virtual, the final forwarder will be executed.

This other example is likely to do funny things (I haven't tried it yet):

struct base {
   void foo() {}
};
struct derived : base {
   void foo() { 
      for ( int i = 0; i < 1000; ++i ) {
         std::cout << data[i];
      }
   }
   int data[1000];
};
int main() {
   base b;
   std::tr1::bind((void (base::*)()) &derived::foo, std::tr1::ref(b))();
}
+1
source

Source: https://habr.com/ru/post/1741410/


All Articles