Unreferenced parameters in base classes

Started by
8 comments, last by Xai 17 years, 5 months ago
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.
Advertisement
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; }};
<a href="http://www.slimcalcs.com>www.slimcalcs.com
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.
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.
___________________________Buggrit, millennium hand and shrimp!
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.
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.
Quote: Original GotW by Herb Sutter
In general, it's not a bad idea to prefer overloading to parameter defaulting

class BaseClass{public:    virtual void AutoSize() { AutoSize(5); }    virtual void AutoSize(int /*padding*/) { }};
___________________________Buggrit, millennium hand and shrimp!
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 implementationvoid 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.
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?
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.

This topic is closed to new replies.

Advertisement