0

I am using a pattern in my program that calls for the calling of different kinds of functors depending on what the object type is. In the code below, the b1 object is explicitly instantiated with derived functor type FunctorX. But when I make the call in the code, the base functor gets called instead of the derived functor. Why is that?

struct Functor
{
  Functor() {}
  ~Functor() {}

  virtual int operator()() { return 33; }
};

struct FunctorX : public Functor
{
  FunctorX() : Functor() {}
  ~FunctorX() {}

  int operator()() { return 44; }
};

template< typename FunctorT >
struct B
{
  B( FunctorT FunctorArg ) : Functor { FunctorArg } {}
  ~B() {}

  FunctorT Functor;
};

int main()
{
  B< Functor > b1 { FunctorX() }; // initialize with derived functor. Derived functor gets instantiated.
  int num = b1.Functor(); // error: calls base functor, not derived functor

  return 0;
}
rtischer8277
  • 496
  • 6
  • 27
  • @Barry changing B's member functor to a ptr lets me do `B< Functor > b1 { new FunctorX() };` and would fix the slicing. But what would the call be on `b1` then? I keep getting `error C2064: term does not evaluate to a function taking 0 arguments` when I call `b1.Functor();`. – rtischer8277 Feb 14 '17 at 22:22
  • @Barry I got it: `int num = (*b1.Functor)();` – rtischer8277 Feb 14 '17 at 22:32

1 Answers1

0

B<Functor> holds an object of type Functor. You can initialize that object with an object of type FunctorX, but when stored, the object will be sliced to type Functor. Just like unsigned int i = std::numeric_limits<unsigned long long>::max(), where the stored value has type unsigned int, even though it's initialized with a value whose type is unsigned long long.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • That's not an example of slicing. – Barry Feb 14 '17 at 21:05
  • @Barry - it's an example of exactly what it says: "the stored value has type `int`, even though it's initialized with a value whose type is `unsigned long long`". And that's the fundamental issue underlying slicing. – Pete Becker Feb 14 '17 at 21:09
  • Narrowing conversions and slicing are different things. – Barry Feb 14 '17 at 21:21
  • @Barry -- yes, they are. I haven't said otherwise. Again: the type of the stored value does not depend on the type of the initializer. – Pete Becker Feb 14 '17 at 21:37