Jump to content
  • Advertisement
Sign in to follow this  
n00body

Selective inheritence (?)

This topic is 3744 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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:
};


Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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:

// composition
class Car
{
Wheel w;
};

is equivalent to:

// private inheritence
class Car : private Wheel
{
};

And in both cases Car is not a Wheel.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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&.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!