jeudi 28 avril 2016

How does respecifying a inherited virtual method allow it to disambiguate correctly?

I was doing some fun stuff with googlemock and decided to split my classes into pure virtual classes and concrete implementations to avoid needing to special casing for my mocks. However, the compiler started complaining that:

error: undefined reference to 'vtable for <ConcreteClass>'

I managed to reproduce the issue with the following:

simple.h:

namespace simple {

class InterfaceA {
 public:
  virtual ~InterfaceA() {}

  virtual int MethodOne() const = 0;
};

class InterfaceB : public InterfaceA {
 public:
  ~InterfaceB() override {}

  virtual int MethodTwo() const = 0;
};

class ImplA : public InterfaceA {
 public:
  ImplA(int to_return);
  ~ImplA() override {}

  int MethodOne() const override;

 private:
  int to_return_;
};

class ImplB : public InterfaceB, public ImplA {
 public:
  ImplB();
  ~ImplB() override {}

  // int MethodOne() const override;
  int MethodTwo() const override;
};
}  // namespace simple

simple.cc

#include "simple.h"

namespace simple {

ImplA::ImplA(int to_return) : to_return_(to_return) {}
int ImplA::MethodOne() const { return to_return_; }

ImplB::ImplB() : ImplA(5) {}
// int ImplB::MethodOne() const { return ImplA::MethodOne(); }
int ImplB::MethodTwo() const { return 2; }
}  // namespace simple

The issue was the bits I have commented out; once I added those things into the files, the compiler and my tests were happy. So intuitively this makes sense, as now there are concrete methods defined for the virtual ones, and the compiler previously doesn't/can't guess which super class methods I wanted.

My question is twofold:

  1. How does the specification of ImplA::MethodOne() allow it to be called as it isn't a static variable?
  2. Is there an implicit ImplA pointer somewhere in the ImplB object at creation time that allows it to call a method on ImplA despite not being a static method?

Aucun commentaire:

Enregistrer un commentaire