Sign in to follow this  

Unity Enforcing inherited classes without pure virtual functions?

This topic is 1826 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

Hi again dear community, I have another conundrum for which that I request your counsel. Heavy sounding introductions aside, I think this should be an easy to answer question.

 

In the realms of OOP there is a tendency to 'over generalise'. I like to use abstract classes but to derive super specific use cases from them. In this case, I have a 'static mesh' class that I'm rather proud of, because it's one of the few things I've coded myself that works as expected. I'm sure many programmers have similar classes in their collection. 

 

Up until now I've been merely playing around with the staticMesh class, setting shaders and shader uniforms in calling code and then calling the 'render' function from the calling code. However, now that my codebase is scaling up in terms of sophistication, I would like to create specific classes that inherit from staticMesh like "palmTreeMesh" that will use a vertexBasedLighting shader (no significant specular term to speak of)

and so will use a render function as follows:

 

//pseudo code!

void PalmTree::Render()
{
  glUseProgram(texturedShader->getHandle());
  texturedShader->UpdateUniforms("MVPMatrix",someValue);
  texturedShader->UpdateUniforms("Time",someValue);

  StaticMesh::Render();
}

StaticMesh::Render() has no business having its code cut and pasted into several different files, it's great how it is.

 

So the main crux of my inquiry is thus:

StaticMesh::Render is not 'pure virtual' so static mesh is not a abstract class. However I'd like to enforce use of inherited, specific meshes

and not messy, lazy code where everything is done in a calling class. How do I do this? Just use a pure virtual 'stub' like so:

 

class BaseClass
{
public:
  virtual void DoSomething();
  virtual void Stub() = 0;
};

class Derived : public BaseClass
{
public:
  void DoSomething();
  void Stub() {};      //declaration and definition of 'stub'
};

 

 

Or is there another alternative to this? Thanks in advance.

 

Share this post


Link to post
Share on other sites
Here's one common approach:
class Widget
{
public:
    void DoSomeStuff()
    {
        CommonBeginningStuff();
        InternalStuff();
        CommonFinishingStuff();
    }

protected:
    virtual void InternalStuff() { }

private:
    void CommonBeginningStuff();
    void CommonFinishingStuff();
};

class SpecificWidget : public Widget
{
protected:
    virtual void InternalStuff()
    {
        // Specificity goes here!
    }
};

Share this post


Link to post
Share on other sites

You could make the base class constructor protected; then only inherited classes can access the base class' constructor, so no non-derived classes can construct the base class. Constructing a MyBase directly then gives the warning: "'MyBase::MyBase()' is protected".

Share this post


Link to post
Share on other sites

Another way would be to mark the destructor of StaticMesh pure virtual, but also provide an implementation.

 

class StaticMesh
{
   virtual ~StaticMesh() =0
   {}
}

 

This forces people to implement derived classes for StaticMesh.

 

Yet another option would be to mark StaticMesh::Render as pure virtual (again leaving the implementation of it intact). This forces inheritors to override Render but still allows them to call the base implementation, although some people will find this confusing.

 

Personally, I'd go with ApochPiQs solution as it communicates the intent most clearly.

Share this post


Link to post
Share on other sites
Another way would be to mark the destructor of StaticMesh pure virtual, but also provide an implementation.

...

 

Yet another option would be to mark StaticMesh::Render as pure virtual (again leaving the implementation of it intact). This forces inheritors to override Render but still allows them to call the base implementation, although some people will find this confusing.

 

That's pretty odd! Is that valid C++? huh.png

Share this post


Link to post
Share on other sites
Another way would be to mark the destructor of StaticMesh pure virtual, but also provide an implementation.

...

 

Yet another option would be to mark StaticMesh::Render as pure virtual (again leaving the implementation of it intact). This forces inheritors to override Render but still allows them to call the base implementation, although some people will find this confusing.

 

That's pretty odd! Is that valid C++? huh.png

Sure. There's nothing with pure virtual functions that stops you from providing an implementation and calling it.

 

In fact, a pure virtual destructor is required to have an implementation and to have it called. Not required by the language syntax, but a derived class' destructor will call its base class' destructor. If you don't provide an implementation for the destructor, you'll get an undefined external symbol linker error.

Share this post


Link to post
Share on other sites

That's pretty odd! Is that valid C++? huh.png

Sure. There's nothing with pure virtual functions that stops you from providing an implementation and calling it.
 
In fact, a pure virtual destructor is required to have an implementation and to have it called. Not required by the language syntax, but a derived class' destructor will call its base class' destructor. If you don't provide an implementation for the destructor, you'll get an undefined external symbol linker error.


That was my opinion as well. I'd read before that it was valid, just obscure, but I just checked my copy of the C++03 standard and now I'm not sure.

 

 

C++ Standard - section10.2
[Note:a function declaration cannot provide both a pure-specifier and a definition—end note]
[Example:
struct C {
virtual void f() = 0 { }; //ill-formed
};
—end example]

Any language standard experts care to clarify?

Share this post


Link to post
Share on other sites
It means that you cannot put both the definition and the pure specifier on the declaration, not that a pure function cannot be defined. Solution:
struct C {
    virtual void f() = 0;
};

void C::f() {
}
edit: And yeah, that was new to me, actually. I thought you could do both, but MSVC doesn't complain about it even with language extensions disabled. Looks like G++ is doing the right thing though. Edited by Brother Bob

Share this post


Link to post
Share on other sites

I've followed swift coder's advice - namely PalmTree HAS a mesh and a shader. Actually makes everything less of a headache than what I was trying. Interesting discussion though!

Share this post


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

  • Similar Content

    • By loyalsheep
      Hey guys!
      Check out the trailer of Airavat. It's a minimalist, space survival game (and hard, very hard) 
      Download on GooglePlay: Airavat
       
    • By anomalystudiospt
      Hey, we are new around here!
      Our team spent the last year developing a prototype game called Rise of The Fey, a game that focuses on a dramatic story with a fast paced gameplay.
      Rise of The Fey is a third-person action-adventure RPG set within a fantasy world called Perrah. In Rise you control Kall, a young spaunian looking for revenge after the death of his beloved.

      We would appreciate if you could take a look at our stuff, tell us what you think and possibly help us out on Indiegogo.
      The prototype is in portuguese, sorry about that!
      Have a good one!
    • By juglar
      Hi guys, we are developing a game called BiteOff! based on Zombies topic. BiteOff! is based on a game strategy mechanics, free to play, where the player has a bunch of zombies and he can distribute them along the map landscape to be able to bite and transform all humans into each level. Humans are controlled by artificial intelligence and they differ each other on capabilities based on different weapons that give them three different levels of aggressiveness to defend against the zombies. The zombies are also presented in three types and they are differentiated by their attack, speed, strength and resistance abilities. Through different achievements, (time to eat all humans, score, among others) the player can access four extra skills that can enhance your attack in real time on next levels as power-ups.
      We are launching a crowdfunding campaign in kickico and we need some helps please visit us on the crowdfunding page https://www.kickico.com/es/campaigns/17824/biteoff-the-videogame 
      Twitter @biteoffthegame
      Facebook
      Clickme!
      Website 
      Clickme!
    • By Lord McMutton
      The world of Ethios is held aloft by massive trees known as the Pillars.
  • Popular Now