Fixng unused formal parameter warnings without making an abstract class - c++

I have a base class and it has virtual functions. The issue is that, the base is allowed to be instanced, but that means that all of its functions need a definition. This causes the compiler to warn me about unused parameters. What can I do to properly get rid of these warnings without making pure virtual functions and making it an abstract class?
example:
class Foo {
public:
virtual void bar(int x) {} //unused formal parameter int x
}
Thanks

Usual solution is:
virtual void bar(int x) { (void)x; }
or:
virtual void bar(int) {}
This prevents the compiler from whinging. Note that this technique isn't restricted to virtual member functions; it should work for any function where you don't intend to use one or more arguments.
On an unrelated note; an instantiable base class with empty member-function definitions doesn't sound like a very good idea; are you sure that you wouldn't be better off just making it abstract?

Is there a problem in using the absolutely most obvious solution?
class Foo {
public:
virtual void bar(int) {}
};
Just remove the parameter name.

For what it's worth, an alternative method is:
virtual void bar(int /*x*/) {}

Related

Do overriding functions need to be specified virtual?

In Cplusplus, in a derived class, if we define a member function to override a member function in its parent class, do we need to declare the one in the derived class to be virtual?
For example, do we need to declare g to be virtual in B in order for it to override A::g? which one of the following is correct for the above purpose?
class A{
public:
void f(){printf("A");}
virtual void g(){printf("A");}
}
class B : public A{
public:
void f(){printf("B");}
void g(){printf("B");}
}
or
class A{
public:
void f(){printf("A");}
virtual void g(){printf("A");}
}
class B : public A{
public:
void f(){printf("B");}
virtual void g(){printf("B");}
}
Thanks.
Once a method is virtual in a class, its child class has also these virtual class even if you don't add virtual to them.
Adding override is a good habit to avoid subtle error:
class A{
public:
void f() { printf("A"); }
virtual void g() { printf("A"); }
};
class B : public A{
public:
void f() { printf("B"); }
void g() override { printf("B"); }
};
No you don't. The function is virtual from the first point in the hierarchy where you declare it as such.
You can and should specify it as override in c++11 and onward. It specifies explicitly to the compiler that you are trying to override a virtual function in a base class. It than emits an error if you misspell the function name, mistype the parameters or do anything else that can be considered as adding an overload of the function. Prior to c++11, the previous mistakes would silently compile.
Defining member functions virtual in derived classes is optional. You can make the override explicit using C++11's override.
They both do the same thing. You don't need to explicitly say virtual in the derived class, as long as it is virtual in the base class.
In Cplusplus, in a derived class, if we define a member function to override a member function in its parent class, do we need to declare the one in the derived class to be virtual?
From the working draft, [class.virtual]/2 (emphasis mine):
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.
So, no. It is not required.
In pre-C++11 era, declaring virtual also the member functions in the derived classes helped the readers understanding what's going on under the hood.
Since C++11, override is the preferred way, for it not only helps the readers, but also it forces a compile-time check so that typos in the declarations don't introduce subtle errors.

C++: Override method which has the same name as the class

Let's say I have a nice looking base class called base:
class base
{
public:
virtual void foo() const = 0;
};
Now, I have a class named foo that I would like to inherit from base and override base::foo:
class foo : public base
{
public:
virtual void foo() const override;
};
This is illegal in C++, as you are not allowed to name a method the same thing as the class (C++ greedily believes methods with the same name as the class are constructors, which are not allowed to have return types). Is there any way around this that doesn't involve changing the name of the class or method? I want external users to be able to create foo classes without the knowledge that there is a method base::foo called by someone else (imagine foo can be both a noun and a verb).
Is there any way around this that doesn't involve changing the name of the class or method?
No, there isn't.
All methods named foo are special in class foo -- they are constructors. Hence, they cannot be overridden virtual member functions.
I'll take a wild guess and just say NO.
You can have a lot of ambiguities in C++ (that sometimes have to be explicitly disambiguated), but I don't even see a way how a compiler or programmer could disambiguate this situation. Well, A programmer can (a function with a return type is obviously not a constructor), but C++ can't.
In C++, the only method that can have the class' name is its constructor.
So, no. You can't.
Okay, here's my (slightly evil) solution...
// Create an intermediate class which actually implements the foo method:
class foo_intermediate : public base
{
public:
virtual void foo() const override;
};
// Derive from that class and forward the constructor along
class foo : public foo_intermediate
{
public:
using foo_intermediate::foo_intermediate;
private:
friend class foo_intermediate;
// Actual implementation for the foo function goes here
void foo_impl() const;
};
// In some CPP file:
void foo_intermediate::foo() const
{
// Need to access the typename foo via namespace (global here)
static_cast<const ::foo*>(this)->foo_impl();
}
Actually calling foo is a bit funny, since this can't work:
void bar()
{
foo x;
x.foo(); // <- illegal attempt to access to the foo constructor
}
You must access through an alias:
void baz()
{
foo x;
base& rx = x;
rx.foo(); // legal
}
As an alternative, you can use a typedef:
class foo_impl : public base
{
public:
virtual void foo() const override;
};
using foo = foo_impl;
This gets around the issue of calling x.foo(), since it no longer appears as a constructor access.
I made a Gist so others could play with the two solutions if they are so inclined.

Virtual functions and default parameters

Lets say I have a class A, B and C
class A{
public:
virtual void f4(){
cerr<<"A::f4()"<<endl;
}
};
class B: public A{
public:
virtual void f4(int n){
cerr<<"B::f4("<<n<<")"<<endl;
}
};
class C: public B{
public:
virtual void f4(int n = 1){
cerr<<"C::f4("<<n<<")"<<endl;
}
};
If I have:
C c;
A& rac = c;
rac.f4();
I was expecting c's version of f4 to be called but that's not what happens. Can someone explain?
Compiling with clang -Wall the following warnings occur:
main.cpp:14:22: warning: 'B::f4' hides overloaded virtual function [-Woverloaded-virtual]
virtual void f4(int n){
^
main.cpp:6:22: note: hidden overloaded virtual function 'A::f4' declared here: different number of parameters (0 vs 1)
virtual void f4(){
^
These warnings explain what's going on. A virtual function is only overridden by another function with the same signature.
B::f4(int) does not override A::f4() because they have different parameter lists. Instead, it is a different virtual function.
So rac.f4() just calls A::f4() which is not overridden.
Since C++11 you can help to detect this problem:
virtual void f4(int n) override {
// ^^^^^^^^
Then the compiler will give an error if this function does not actually override something from the base.
Because the signatures of f4 don't match between A and B/C classes.
This is A's function signature for f4:
void A::f4() // no parameters
B and C use this function signature
void B::f4(int n)
If you are doing to override a method, it needs to have the same return type and identical parameter list. Otherwise, even if the method in the derived class has the same name as the parent class, C++ will don't consider that an override.
FWIW, C::f4 does override B::f4. The default parameter you introduce on class C doesn't influence the virtual methods override behavior. And this is the exact reason why, on my team, we disallow overloading methods with different signatures and banning default parameters. Because it leads to bugs like this.
Here's C's v-table (the methods available on it):
void C::f4(); // no parameters, overrides A::f4()
void C::f4(int n); // overrides B::f4()

C++ same name for non-virtual function in derived class conflicts with `final` specifier

This has the feeling of a complete newbie question, but why does the following code not compile when the final specifier is used for B::operator()?
struct A
{
virtual void operator()() const = 0;
};
// the CRTP-component is not really necessary here
// but it possibly makes more sense in that it could be applied like this in reality
//
template<typename Derived>
struct B : A
{
virtual void operator()() const override final
{
static_cast<Derived const&>(*this).operator()();
}
};
struct C : B<C>
{
void operator()() const
{
//do something
}
};
int main()
{
C()();
}
G++ prints the following error message:
main.cpp:17:14: error: virtual function 'virtual void C::operator()() const'
void operator()() const
^
main.cpp:9:22: error: overriding final function 'void B<Derived>::operator()() const [with Derived = C]'
virtual void operator()() const override final
^
I would have thought it works as the non-virtual C::operator() does not override the virtual functions in its base classes? How can I bring this to work (--without changing the name of C::operator())?
EDIT: As pointed out by several users, the answer is simply that the virtual-keyword in the derived class is redundant (whereas I thought leaving it out would prevent from inheriting). However, the goal I had in asking this -- namely a consistent interface throughout the dynamic and static inheritance hierarchy -- can be solved by using a non-virtual operator[] throughout and couple classes A and B by a virtual function apply:
struct A
{
void operator()() const
{
this->apply();
}
protected:
virtual void apply() const = 0;
};
template<typename Derived>
struct B : A
{
void operator()() const
{
static_cast<Derived const&>(*this).operator()();
}
protected:
virtual void apply() const override final
{
this->operator()();
}
};
struct C : B<C>
{
void operator()() const
{
//do something
}
};
int main()
{
C()();
}
If a function is declared virtual in a base class, then a function declared with the same name and parameter list is implicitly virtual in derived classes, whether or not you use the virtual keyword. You cannot make C::operator()() non-virtual.
A function in a derived class with the same signature as a virtual function in a base class overrides that virtual function from the base class. That makes it a virtual function, even if/though the declaration in the derived class doesn't use the virtual key word.
That can't be changed, so if you really need to have a function with the same name in a derived class that doesn't override the virtual function from the base class (and in the process, become virtual itself and in this case, violate the final in B) you'll need to change the signature of the function in the derived class. That can mean a different name, different parameter list, or different qualifiers. I'd treat the latter two with extreme caution though--the compiler will be able to sort out the mess you've made, but many human readers may (very easily) be surprised.
If I were reviewing such code, I'd probably cite this as a problem, and the author would need to provide very solid reasoning for why it was truly necessary to get it approved.
As an override (because it has the same signature as the virtual function in a base class), the override conflicts with the final specified in its base class.
One fix (or rather workaround) is to give that function a defaulted argument, so that it has a different type and hence not an override, and a better approach is to fix the design.

Is it possible to prevent a member function from being redefined?

I would like a class B not to be able to redefine one of the member function of its base class A. Is there a way to do that?
EDIT:
Thanks for the answers. Can I prevent non-virtual member functions from being overridden as well?
If you mean disallowing a derived class to override a virtual function of its base class, C++11 introduced a way to do that with a final virt-specifier (as it's called in the standard):
struct B{
virtual void f() final;
};
struct D : B{
void f(); // error: 'B::f' marked 'final'
};
I don't know which compilers support that, though. Probably GCC 4.7 and Clang.
If your methods are virtual, in C++11 you can prevent overriding them with final.
class A
{
public:
virtual void foo() final;
};
class B : public A
{
public:
void foo(); // <-- error
};
You can't prevent hiding.
Can I prevent non-virtual member functions from being overridden as
well?
No you can't, BUT from another side you can... if you're not shore if will you acctualy override base method or not in your derived class you can check whther you're overriding an method or not using a keywod override
when applying that keywod to your method you make shore that you accutaly realy want override that mathod.
so if signature of inherted method is the same as the signature of base method you'll get compile time error, say that derived method does not override base method.
so using override keyword you are telling the compiler that you DO NOT want to everride it.
by not using override keywod you never know wether you override it or not.
consider following example:
class A
{
public:
void f() {std::cout << "A";}
};
class B : public A
{
public:
void f() override {std::cout << "B";}
};
this result in compile time error because you can't override base method.
by not using the override keyword you'll of course be able to override it.
override keywod is introduced in C++0x standard and is supported by visual studio 2010.