Sign in to follow this  
Kest

Unreferenced parameters in base classes

Recommended Posts

Sorry for bombarding the forum. This is another one I'm a little confused with. I have a situation like this..
class BaseClass
{
public:

    // Optional function - doesn't need to be implemented by derived objects
    virtual void Function(int x, int y, int mouse_cap) { }
};

// The warning is fixed with..

class BaseClass
{
public:
    virtual void Function(int,int,int) { }
};


The compiler is throwing a warning that x and y are unreferenced. That can be fixed by removing the variable instance names. But what does that really do, other than making the function declaration far less readable? What happens down the road when I need a derived object to implement this function, but no longer remember what the parameters actually are? Is there any other way to fix this situation? Thanks for information.

Share this post


Link to post
Share on other sites
Option 1:
What you said, remove the variable name.

Option 2:
class BaseClass
{
public:

// Optional function - doesn't need to be implemented by derived objects
virtual void Function(int x, int y, int mouse_cap)
{ (void)x; (void)y; (void)mouse_cap; }
};

Share this post


Link to post
Share on other sites
Your compiler is warning you that x, y, and mouse_cap are declared, but unused in the function.

I originally suggested going with an abstract class, but that doesn't meet your requirement of optional overrides. It just seems odd that you have a function that does nothing in a base class, but that is optionally overrided. Can someone provide an example of where this is necessary? It seems there should be a better way to do this.

Edit: spelling.

Share this post


Link to post
Share on other sites
Quote:
Original post by Kest
The compiler is throwing a warning that x and y are unreferenced. That can be fixed by removing the variable instance names.
...
Is there any other way to fix this situation?

a) Disable the warning in the options/at the command line.
b) Disable the warning with a compiler specific pragma.
c) Put the names in comments:

virtual void Function(int /*x*/, int /*y*/, int /*mouse_cap*/) { }




d) Put the names in a macro:

#define UNUSED(X)

virtual void Function(int UNUSED(x), int UNUSED(y), int UNUSED(mouse_cap)) { }




e) Use a (possibly compiler specific) idiomatic NOP trick to make the warning go away:

virtual void Function(int x, int y, int mouse_cap)
{
x=x;
y=y;
mouse_cap=mouse_cap;
}






I would go with option c).

Edit: OK, seems I'm a slow typer. e) is ofcourse a variant of Option 2 posted above. This highlights the fact that different people will expect different idiomatic expressions to do this, and may get confused by others.

Share this post


Link to post
Share on other sites
Quote:

That can be fixed by removing the variable instance names. But what does that really do, other than making the function declaration far less readable? What happens down the road when I need a derived object to implement this function, but no longer remember what the parameters actually are? Is there any other way to fix this situation?


It does nothing, actually. There are no issues with respect to subclasses later overriding the function, the only cost is readability. You can solve that by placing the intended variable names in comments, et cetera, as has been previously shown.

Subclasses overriding the function later are free to rename the parameters if they like. Likewise, the class itself is free to rename the parameters (the declaration of the function can have different parameter names from the definition). The names are purely for your use and are not part of the signature at all.

Share this post


Link to post
Share on other sites
Is there any way to remove the parameter instance name without breaking the ability to assign default values?

class BaseClass
{
public:
virtual void AutoSize(int padding = 5) { }

... vs ...

virtual void AutoSize(int /*padding*/) { }
};

class DerivedClass
{
public:
void AutoSize(int padding = 5)
{
Resize( GetSize() + padding );
}
};

.......

BaseClass *ptr = new DerivedClass;
ptr->AutoSize(); // Won't work with AutoSize(int); version


Thanks much for the suggestions.

Share this post


Link to post
Share on other sites
look, the interface is defined by the base class ... not the derived classes implementation of it, so further derived classes will not be in any way affected by the decision to omit variable names ... but make sure you do it in the implementation and not the class header (meaning of course you can't use the convienient syntax you initially favored).


class Base
{
public:
// Optional function - doesn't need to be implemented by derived objects
virtual void Function(int x, int y, int mouse_cap);
};

// stub implementation
void Base::Function(int, int, int)
{
// any appropriate code here
}

class Derived : public Base
{
public:
};

class FurtherDerived : public Derived
{
public:
virtual void Function(int x, int y, int mouse_cap);
};

void FurtherDerived::Function(int x, int y, int mouse_cap)
{
// do stuff here
}

class EvenFurtherDerived : public FurtherDerived
{
public:
virtual void Function(int x, int y, int mouse_cap);
};

void EvenFurtherDerived::Function(int x, int y, int)
{
// note this function didn't need mouse_cap, so it leaves it unnamed
}



usually I favor the commented out approach when I simply am not using SOME of the parameters, and the no-name approach when I am using NONE of the parameters. This allows the commented out versions to be proper placeholders when relevant, but allows the proper ignoring of the information that obviously has no relevance in the later case.

Share this post


Link to post
Share on other sites
Quote:
Original post by Xai
look, the interface is defined by the base class ... not the derived classes implementation of it, so further derived classes will not be in any way affected by the decision to omit variable names

I realize that. That wasn't my concern. My only concern was relying on comments to remember what is what. I'm the type of programmer that would go back to a header to rename an "int wind" variable to match the "int wind_velocity" in the source, if I later change it. Not because it has an effect, but because the names convert an undefined chunk of 4 bytes into something meaningful. I love when I type Object->StopASAP(.. and all I get for reference is "Class::StopASAP(int,int,int,int,float)". Yay, off to the documentation I go. Or with my own code, off to find the header to look at comments, which is bad enough.

Quote:
... but make sure you do it in the implementation and not the class header (meaning of course you can't use the convienient syntax you initially favored).

I really like this idea. It totally solves my problem.

Quote:
Original post by Absolution
It just seems odd that you have a function that does nothing in a base class, but that is optionally overrided. Can someone provide an example of where this is necessary? It seems there should be a better way to do this.

Doesn't it just mean the derived objects can have optional functionality? Why does that seem odd? The only alternative is to make the function pure, then declare empty versions of the interface functions in every class that derives from the base and does not need the functionality.

For an example, my base GUI object has the AutoSize() function. Window, group, and text box controls use this funciton. All other controls do nothing when auto-sized. Specific classes of controls are hidden from calling code. Calling code only has visibility of the base class. How can that code signal to auto-size a control without using the base class interface?

Share this post


Link to post
Share on other sites
Kest, I totally agree with what you say you do in the top response section ... I rename things to be correct at all times, always. So my first part which you responded to makes more sense AFTER you read the second part you responded to. (in other words, I was saying, omiting the names in the implementation doesn't have any affect, BECAUSE you haven't omitted them in the header, not because C++ ignores them).

But anyway, I know you understand what I was saying, jut clarifying for other readers. Good luck.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this