Selective inheritence (?)

Started by
9 comments, last by Dranith 15 years, 9 months ago
Situation: Using Bullet Physics engine's math library as basis for my own code, to avoid reinventing the wheel. Ultimately, I'm trying to insulate my engine from the implementation. Example: Using btVector3, I have my Vec3 class inherit from it. So I can pass it to any function/method that can take a btVector3, and make use of its methods. Dilemma: I don't completely agree with some of their design decisions, or method naming. So I would like to implement my own methods, while obscuring some of theirs. I've considered using private inheritance, and then making my methods forward their args to the parent-class' methods. However, private inheritance won't allow me to pass my Vec3 to functions taking btVector3. Question: Is there any way to get around this problem? Or will I just have to inherit everything, and say in my documentation "Don't use XX method from YY class"? Thanks for any help you can provide.

[Hardware:] Falcon Northwest Tiki, Windows 7, Nvidia Geforce GTX 970

[Websites:] Development Blog | LinkedIn
[Unity3D :] Alloy Physical Shader Framework

Advertisement
Shadow the function you do not want to be accessible in the derived class:

class Base{public:	void foobaz(){ std::cout << "base::foobaz" << std::endl; }};class Derv : public Base{private:	void foobaz(){ std::cout << "derv::foobaz" << std::endl; }public:};
This should work

class Vec3 : private btVector3{public:	operator btVector3&() { return *this; }};


EDIT: Is this even needed? I think it will implicitly downcast even if it's private inheritance?
Quote:Original post by lexs
This should work

*** Source Snippet Removed ***

EDIT: Is this even needed? I think it will implicitly downcast even if it's private inheritance?


That is pretty unsafe.

Private inheritance does not provide polymorhic behavior. Private inheritance is equivalent to composition.

So this example:
// compositionclass Car{   Wheel w;};

is equivalent to:
// private inheritenceclass Car : private Wheel{};

And in both cases Car is not a Wheel.
Quote:Using btVector3, I have my Vec3 class inherit from it. So I can pass it to any function/method that can take a btVector3, and make use of its methods.

Don't do it. If you want to use btVector3 for your math stuff, just do it. If you want your own vector class, use your own vector class (possibly based on the btVector3 code), and provide conversion functions in both directions. Inheritance is a square peg to this particular round hole.
Quote:Original post by fpsgamer
That is pretty unsafe.

Private inheritance does not provide polymorhic behavior. Private inheritance is equivalent to composition.

Yeah, my brain got confused when I tested on an unused class.

Why not composite instead of inherit? That way you have full control over member access and even naming conventions. You would basically be creating an adapter, or wrapper for their class to fit your needs. I don't feel inheritance is the right way to go when you need to remove functionality like this. Unless you specifically need to upcast to the Bullet btVector3, you an probably get away with just some sort of accessor that returns a btVector3&.
Quote:Original post by n00body

Dilemma: I don't completely agree with some of their design decisions, or method naming. So I would like to implement my own methods, while obscuring some of theirs. I've considered using private inheritance, and then making my methods forward their args to the parent-class' methods. However, private inheritance won't allow me to pass my Vec3 to functions taking btVector3.


Ah, so the real problem is their naming convention.

If that's the issue, you might as well rename the library itself. It's as good as solution as any when dealing with non-existent problems.

The answer to what a third-party library looks like, or what naming convention it uses is not really an engineering one, as long as it doesn't cause conflicts.

With this in mind, do whatever you want, there is no technical decision which would warrant such a task, or the effort spent on it. A third-party library "is". Then it either fulfills your needs, or it doesn't. But trying to morph something into something it is not has been, in the long term, proven as futile.

The only productive way to approach such a problem is to build an interface which has your design and your naming convention. Then, implement that interface using their methods. With interface I mean header file, which doesn't reference the library in question in any way whatsoever. All mapping is performed inside implementation (cpp).

But trying to mix and match headers will result in too many problems.
An entirely different approach is to forget about which specific type your functions take and interact with them generically through traits e.g. for a dot-product

template<typename V1, typename V2>typename widest<    typename element<V1>::type,     typename element<V2>::type>::type dot(const V1 &lhs, const V2 &rhs){    BOOST_STATIC_ASSERT(dimensions<V1>::value == dimensions<V2>::value);    typename widest    <        typename element<V1>::type,         typename element<V2>::type    >    ::type ret(0);     for (std::size_t i = 0; i != dimensions<V1>::value; ++i)        ret += at(lhs, i) * at(rhs, i); // at() forwards to access_traits<>::at(), perhaps    return ret;}


Not to everyone's tastes, but it might suit your needs. It insulates you completely from the underlying library you choose, assuming you can define suitable traits and concepts.

I have considered just implementing my own types, in a similar fashion to theirs. My two main concerns were not wasting effort writing more code, when basically the same thing was already written in the API I planned to use.

Also, and possibly more important, I was concerned with performance. Specifically, do I stand to lose performance at the border of my engine and their API, when I have to convert my data to something it likes?

I figured, having my classes inherit from theirs would allow me to pass my data through with no conversion step. Does this really make that much of a difference? Or would my time be better spent just writing my own classes, and converting their data at the border?

[Edited by - n00body on July 18, 2008 9:50:16 PM]

[Hardware:] Falcon Northwest Tiki, Windows 7, Nvidia Geforce GTX 970

[Websites:] Development Blog | LinkedIn
[Unity3D :] Alloy Physical Shader Framework

This topic is closed to new replies.

Advertisement