开发者

Does an inherited function not count as an implementation?

开发者 https://www.devze.com 2023-03-30 16:40 出处:网络
I have a function defined in a superclass, InteractorStyle. Then I have another class that requires that function to be impl开发者_如何学运维emented (pure virtual), PointSelector. Then a subclass of P

I have a function defined in a superclass, InteractorStyle. Then I have another class that requires that function to be impl开发者_如何学运维emented (pure virtual), PointSelector. Then a subclass of PointSelector, PointSelector2D, is instantiated. The compiler complains that I can't instantiate an abstract class because MyFunction() is not implemented. Why doesn't the function that gets inherited from InteractorStyle count as this implementation?

#include <iostream>

// I can't change these:
class InteractorStyle
{
  void MyFunction(){}
};

class PointSelector
{
  virtual void MyFunction() = 0;
};

class PointSelector2D : public InteractorStyle, public PointSelector
{

};


int main()
{
  PointSelector2D a;
  return 0;
}


Because with multiple inheritance, you have now inherited two unrelated functions, one from each base class. They just so happen to have the same name as each other (in fact, they don't; one is called InteractorStyle::MyFunction, the other is called PointSelector::MyFunction).

But one does not override the other (at least, not in the sense that you are hoping for).


In the code that you present InteractorStyle::MyFunction is non-virtual. Thus it cannot override or "implement" any virtual function.

But even if you add a virtual keyword there, InteractorStyle::MyFunction still won't serve as implementation of PointSelector::MyFunction in your derived class PointSelector2D.

In order to serve as implementation, InteractorStyle::MyFunction must be defined in a class that is derived from PointSelector. But if you simply do that, let InteractorStyle inherit from PointSelector, then with the rest of the code unchanged it still won’t be an implementation down in PointSelector2D. And it will be worse, it will introduce ambiguity!

Why? Because PointSelector2D then contains two PointSelector base class sub-objects, one from InteractorStyle (where you added the inheritance), and one from its direct inheritance from PointSelector.

So, if you need to keep the code such that InteractorStyle2D inherits explicitly from PointSelector, and you want to bring in implementation via inheritance, sort of like in Java, then …

the solution is to recognize that PointSelector is effectively an interface class, and to inherit virtually from it, which ensures that there’s only one base class sub-object:

// This class defines an "interface".
class PointSelector
{
public:
    virtual void myFunction() = 0;
};

// Derived virtually from the interface
class InteractorStyle
    : virtual public PointSelector
{
public:
    void myFunction(){}
};

class PointSelector2D
    : public virtual PointSelector
    , public InteractorStyle
{};


int main()
{
  PointSelector2D a;        // Ooh, it works! :-)
  a.myFunction();           // Yay! No ambiguity!
}

But what about the ambiguity for lookup? Well, the virtual derivation fixed that too, because it brings in a special rule called dominance, where essentially the compiler recognized that due to the virtual derivation, PointSelector::myFunction and InteractorStyle::myFunction must be the same, and that the former is declaration while the latter in a derived class must be an implementation. It's a bit difficult to explain clearly since I’ve never found the standard’s clauses about it, but at least in C++0x N3290 you now find “dominance” in the index, referring to the non-normative dominance example in §10.2/10 and §10.2/11.

But, anyway, this is how to do implementation inheritance Java-style in C++.

Cheers & hth.,

0

精彩评论

暂无评论...
验证码 换一张
取 消