Is there any issue with partially overriding a set of virtual functions defined by a base class?
My compiler provides the following warning:
overloaded virtual function "MyBaseClass::setValue" is only partially overridden in class "MyDerivedClass".
The classes look like this:
class MyBaseClass
{
public:
virtual void setValue(int);
virtual void setValue(SpecialType*);
}
class MyDerivedClass : public MyBaseClass
{
public:
virtual void setValue(int);
}
The easy way to get rid of this warning is to use different names for the base functions, but I wanted to know if there was any compelling reason to fix this specific warning. I do not believe this violates the C++ standard. My guess is that it's to warn a programmer that they may have forgotten to implement the behavior for all possible input types. In our case, it is intentional to exclude some of the specific types.
Would you discourage suppressing this warning altogether?
The override for setValue(int) hides setValue(SpecialType*) of the base class (see the C++ FAQ Lite), so if you try to call setValue(new SpecialType()) you will get an error.
You can avoid this by adding a using directive to the derived class that "imports" the overloads from the base class:
class MyDerivedClass : public MyBaseClass
{
public:
using MyBaseClass::setValue;
virtual void setValue(int);
};
The warning is correct, it's called "name hiding". A variable of type MyDerivedClass cannot call setValue(SpecialType*).
Now I'm going to blatantly rip off someone else's blog:
Overloading and name hiding in C++
In a phone conversation with Brad last night, he told me about a strange problem he's encountered in his new C++ job. Granted, it's probably no big deal to people with extensive C++ experience, but to those of us who live in managed code worlds, this seemed strange.
In C++, when you have a class with an overloaded method (member function, whatever you want to call it), and you then extend and override that method, you must override all of the overloaded methods.
I understand the case where you have changed a method signature in a child class, thereby invalidating the established interface. In this case, though, it seems counterintuitive, since you're not changing the interface, but selectively overriding. Which is different.
For example:
class FirstClass
{
public:
virtual void MethodA (int);
virtual void MethodA (int, int);
};
void FirstClass::MethodA (int i)
{
std::cout << "ONE!!\n";
}
void FirstClass::MethodA (int i, int j)
{
std::cout << "TWO!!\n";
}
Simple class here with two methods (or one overloaded method). You want to override the two-parameter version, so you continue with the following:
class SecondClass : public FirstClass
{
public:
void MethodA (int);
};
void SecondClass::MethodA (int i)
{
std::cout << "THREE!!\n";
}
Now, when you use an instance of SecondClass, most Java or C# programmers might assume you can call:
int main ()
{
SecondClass a;
a.MethodA (1);
a.MethodA (1, 1);
}
However, the second call won't work, since the two-parameter MethodA is not visible. You can get a pointer and up-cast to FirstClass, but your SecondClass instance doesn't inherit the non-overridden methods directly.
It's clear that the compiler wants to warn you: you created a subclass that behaves differently when giving it an int, but you didn't change it's behavior when giving it a SpecialType*.
Although this might be the intention, it is very very possible that the changed behavior is also needed for the other overloaded virtual functions.
I wish the compiler had warned me harder, the time I ignored it! My overridden method turned out to compile and work well in my scenario, but some other scenario's went really wrong due to the overload not being overridden.
Think twice before you disable that warning!
If you want the original behavior kept, it's easy to just call the parent function:
class MyDerivedClass : public MyBaseClass {
virtual void setValue(int);
// explicit: keep original behavior for SpecialType
virtual void setValue( SpecialType* p ) { MyBaseClass::setValue(p); }
};
Related
i'm new to c++, i'm learning dynamic polymorphism. But i'm getting really confused in the details. can anyone explain why we use virtual, override and use pure virtual functions even though we can just overload methods??
Thanks
Look at this code:
class Base
{
public:
void my_method() { std::cout << "base" << std::endl; }
};
class Derived : public Base
{
public:
void my_method() { std::cout << "derived" << std::endl; }
};
int main()
{
Base* object = new Derived;
object->my_method();
delete object;
return 0;
}
Implemented: http://www.cpp.sh/4z4p
The output of this is "base", despite object being constructed as Derived. Add a virtual in front of Base::my_method and this changes. Add an override to Derived::my_method and it won't compile should it not actually override.
Note that while here things are easy and clear, later on you have more complicated cases and you might think that you override while you actually don't. For example, you might change the signature of the method in the base class while forgetting to change it in the subclass, or the other way around.
Pure virtual methods are to show that something is to be implemented. The idea is that you create an interface which only determines what a set of classes is supposed being able to do but which does not do anything by itself. A pure virtual class, that is. In Java, interface is actually be a keyword on it's own.
If your base has a pure virtual method and your subclass does not implement it, your compiler will result in error, which is useful.
One thing not in your list but still somewhat useful is the keyword final with which you disallow deriving a class, essentially the opposite of an interface.
overloading functions means having the same function name with a different signature - i.e. different parameters and/or return type.
int test(int a)
void test();
here, int test(int a) is an overload of void test().
virtual only exists in the context of inheritance. it means "Hey, this function can be overriden in subclasses".
override is just a hint that you actually intend to override a virtual function.
pure virtual functions look like this:
void virtualFunction() = 0;
and means that this function is abstract (in C# and Java terms), i.e. it does not contain an implementation in this class, but is meant to be overriden in one of it's subclasses. Infact you cannot instantiate a class with a non-overriden pure virtual function.
I'm confused as to why the C++ compiler won't accept this:
class Foo {
private: void Baz() { }
};
class Bar {
public: void Baz() {
};
class FooBar : public Foo, public Bar { };
void main() {
FooBar fb;
fb.Baz();
}
The error gcc gives is:
request for member ‘Baz’ is ambiguous
candidates are: void Bar::Baz()
void Foo::Baz()
but isn't it obvious that I want Bar::Baz(), since Foo::Baz() is private? Why won't the compiler disambiguate here?
Name resolution works in two stages. First the name is looked up then the name is checked for access. If the name look up is ambiguous then the access is never considered.
As to why, maybe it's a deliberate language design, but I think more likely it's just to simplify the process of resolving names. The rules are fiendishly complicated already.
It's not obvious - you might have wanted to call the private member (if that was possible).
Formally, the language rules say that the name is resolved first and the best overload is selected. Only after that is there a check for accessibility.
In order to allow this, it would need to consider whether or not you are in a context that allows you to call a private method or not. If this were allowed then the call:
fb.Baz()
could have completely different functionality depending on whether you were calling it from a public or private context. And that's not really inline with the way the language works.
As others have said, first the name is looked up, then access restrictions are applied. You can work around this by explicitly calling the method you wish, as in
fb.Bar::Baz()
Access restrictions don't affect inheritance. You always inherit everything from all base classes. In your case that may seem unnecessary, but consider a slightly modified version where the private function is virtual:
class Base
{
virtual void secret_power() { /* innocent default */ }
public:
void use_me() { secret_power(); }
};
class Derived : public Base
{
virtual void secret_power() { /* overriding implementation here */ }
};
Now for any Base& you can always call the non-virtual public interface use_me(), but your derived classes provide the implementation by means of a private virtual.
I have a virtual base class function which should never be used in a particular derived class. Is there a way to 'delete' it? I can of course just give it an empty definition but I would rather make its attempted use throw a compile-time error. The C++11 delete specifier seems like what I would want, but
class B
{
virtual void f();
};
class D : public B
{
virtual void f() = delete; //Error
};
won't compile; gcc, at least, explicitly won't let me delete a function that has a non-deleted base version. Is there another way to get the same functionality?
It is not allowed by the standard, however you could use one of the following two workarounds to get a similar behaviour.
The first would be to use using to change the visibility of the method to private, thus preventing others from using it. The problem with that solution is, that calling the method on a pointer of the super-class does not result in a compilation error.
class B
{
public:
virtual void f();
};
class D : public B
{
private:
using B::f;
};
The best solution I have found so far to get a compile-time error when calling Ds method is by using a static_assert with a generic struct that inherits from false_type. As long as noone ever calls the method, the struct stays undefied and the static_assert won't fail.
If the method is called however, the struct is defined and its value is false, so the static_assert fails.
If the method is not called, but you try to call it on a pointer of the super class, then Ds method is not defined and you get an undefined reference compilation error.
template <typename T>
struct fail : std::false_type
{
};
class B
{
public:
virtual void f()
{
}
};
class D : public B
{
public:
template<typename T = bool>
void
f()
{
static_assert (fail<T>::value, "Do not use!");
}
};
Another workaround would be to throw an exception when the method is used, but that would only throw up on run-time.
The standard does not allow you to delete any member of a base-class in a derived class for good reason:
Doing so breaks inheritance, specifically the "is-a" relationship.
For related reasons, it does not allow a derived class to define a function deleted in the base-class:
The hook is not any longer part of the base-class contract, and thus it stops you from relying on previous guarantees which no longer hold.
If you want to get tricky, you can force an error, but it will have to be link-time instead of compile-time:
Declare the member function but don't ever define it (This is not 100% guaranteed to work for virtual functions though).
Better also take a look at the GCC deprecated attribute for earlier warnings __attribute__ ((deprecated)).
For details and similar MS magic: C++ mark as deprecated
"I have a virtual base class function which should never be used in a particular derived class."
In some respects that is a contradiction. The whole point of virtual functions is to provide different implementations of the contract provided by the base class. What you are trying to do is break the contract. The C++ language is designed to prevent you from doing that. This is why it forces you to implement pure virtual functions when you instantiate an object. And that is why it won't let you delete part of the contract.
What is happening is a good thing. It is probably preventing you from implementing an inappropriate design choice.
However:
Sometimes it can be appropriate to have a blank implementation that does nothing:
void MyClass::my_virtual_function()
{
// nothing here
}
Or a blank implementation that returns a "failed" status:
bool MyClass::my_virtual_function()
{
return false;
}
It all depends what you are trying to do. Perhaps if you could give more information as to what you are trying to achieve someone can point you in the right direction.
EDIT
If you think about it, to avoid calling the function for a specific derived type, the caller would need to know what type it is calling. The whole point of calling a base class reference/pointer is that you don't know which derived type will receive the call.
What you can do is simply throwing an exception in the derived implementation. For example, the Java Collections framework does this quite excessively: When an update operation is performed on a collection that is immutable, the corresponding method simply throws an UnsupportedOperationException. You can do the same in C++.
Of course, this will show a malicious use of the function only at runtime; not at compile time. However, with virtual methods, you are unable to catch such errors at compile time anyway because of polymorphism. E.g.:
B* b = new D();
b.f();
Here, you store a D in a B* variable. So, even if there was a way to tell the compiler that you are not allowed to call f on a D, the compiler would be unable to report this error here, because it only sees B.
I have a virtual base class function which should never be used in a particular derived class.
C++11 provides a keyword final which prevents a virtual function being overriden from.
Look: http://en.cppreference.com/w/cpp/language/final .
class B
{
virtual void f() final;
};
class D : public B
{
// virtual void f(); // a compile-time error
// void f() override; // a compile-time error
void f(); // non-virtual function, it's ok
};
I'm confused as to why the C++ compiler won't accept this:
class Foo {
private: void Baz() { }
};
class Bar {
public: void Baz() {
};
class FooBar : public Foo, public Bar { };
void main() {
FooBar fb;
fb.Baz();
}
The error gcc gives is:
request for member ‘Baz’ is ambiguous
candidates are: void Bar::Baz()
void Foo::Baz()
but isn't it obvious that I want Bar::Baz(), since Foo::Baz() is private? Why won't the compiler disambiguate here?
Name resolution works in two stages. First the name is looked up then the name is checked for access. If the name look up is ambiguous then the access is never considered.
As to why, maybe it's a deliberate language design, but I think more likely it's just to simplify the process of resolving names. The rules are fiendishly complicated already.
It's not obvious - you might have wanted to call the private member (if that was possible).
Formally, the language rules say that the name is resolved first and the best overload is selected. Only after that is there a check for accessibility.
In order to allow this, it would need to consider whether or not you are in a context that allows you to call a private method or not. If this were allowed then the call:
fb.Baz()
could have completely different functionality depending on whether you were calling it from a public or private context. And that's not really inline with the way the language works.
As others have said, first the name is looked up, then access restrictions are applied. You can work around this by explicitly calling the method you wish, as in
fb.Bar::Baz()
Access restrictions don't affect inheritance. You always inherit everything from all base classes. In your case that may seem unnecessary, but consider a slightly modified version where the private function is virtual:
class Base
{
virtual void secret_power() { /* innocent default */ }
public:
void use_me() { secret_power(); }
};
class Derived : public Base
{
virtual void secret_power() { /* overriding implementation here */ }
};
Now for any Base& you can always call the non-virtual public interface use_me(), but your derived classes provide the implementation by means of a private virtual.
I have a base class with a virtual function and I want to override that function in a derived class. Is there some way to make the compiler check if the function I declared in the derived class actually overrides a function in the base class? I would like to add some macro or something that ensures that I didn't accidentally declare a new function, instead of overriding the old one.
Take this example:
class parent {
public:
virtual void handle_event(int something) const {
// boring default code
}
};
class child : public parent {
public:
virtual void handle_event(int something) {
// new exciting code
}
};
int main() {
parent *p = new child();
p->handle_event(1);
}
Here parent::handle_event() is called instead of child::handle_event(), because the child's method misses the const declaration and therefore declares a new method. This could also be a typo in the function name or some minor difference in the parameters types. It can also easily happen if the interface of the base class changes and somewhere some derived class wasn't updated to reflect the change.
Is there some way to avoid this problem, can I somehow tell the compiler or some other tool to check this for me? Any helpful compiler flags (preferably for g++)? How do you avoid these problems?
Since g++ 4.7 it does understand the new C++11 override keyword:
class child : public parent {
public:
// force handle_event to override a existing function in parent
// error out if the function with the correct signature does not exist
void handle_event(int something) override;
};
Something like C#'s override keyword is not part of C++.
In gcc, -Woverloaded-virtual warns against hiding a base class virtual function with a function of the same name but a sufficiently different signature that it doesn't override it. It won't, though, protect you against failing to override a function due to mis-spelling the function name itself.
As far as I know, can't you just make it abstract?
class parent {
public:
virtual void handle_event(int something) const = 0 {
// boring default code
}
};
I thought I read on www.parashift.com that you can actually implement an abstract method. Which makes sense to me personally, the only thing it does is force subclasses to implement it, no one said anything about it not being allowed to have an implementation itself.
In MSVC, you can use the CLR override keyword even if you're not compiling for CLR.
In g++, there's no direct way of enforcing that in all cases; other people have given good answers on how to catch signature differences using -Woverloaded-virtual. In a future version, someone might add syntax like __attribute__ ((override)) or the equivalent using the C++0x syntax.
In MSVC++ you can use keyword override
class child : public parent {
public:
virtual void handle_event(int something) <b>override</b> {
// new exciting code
}
};
override works both for native and CLR code in MSVC++.
Make the function abstract, so that derived classes have no other choice than to override it.
#Ray Your code is invalid.
class parent {
public:
virtual void handle_event(int something) const = 0 {
// boring default code
}
};
Abstract functions cannot have bodies defined inline. It must be modified to become
class parent {
public:
virtual void handle_event(int something) const = 0;
};
void parent::handle_event( int something ) { /* do w/e you want here. */ }
I would suggest a slight change in your logic. It may or may not work, depending on what you need to accomplish.
handle_event() can still do the "boring default code" but instead of being virtual, at the point where you want it to do the "new exciting code" have the base class call an abstract method (i.e. must-be-overridden) method that will be supplied by your descendant class.
EDIT: And if you later decide that some of your descendant classes do not need to provide "new exciting code" then you can change the abstract to virtual and supply an empty base class implementation of that "inserted" functionality.
Your compiler may have a warning that it can generate if a base class function becomes hidden. If it does, enable it. That will catch const clashes and differences in parameter lists. Unfortunately this won't uncover a spelling error.
For example, this is warning C4263 in Microsoft Visual C++.
C++11 override keyword when used with the function declaration inside the derived class, it forces the compiler to check that the declared function is actually overriding some base class function. Otherwise, the compiler will throw an error.
Hence you can use override specifier to ensure dynamic polymorphism (function overriding).
class derived: public base{
public:
virtual void func_name(int var_name) override {
// statement
}
};
class MyClass {
public:
MyClass() {}
virtual uint32_t someFunction(bool param = false) {
if (param) {
std::cout << "This is an example virtual function with default code" << std::endl;
}
return 1100; //just for return something
};
then you can override the function as you need
class MyClass2 : public MyClass {
public:
MyClass2();
uint32_t someFunction(bool param) override;
};
uint32_t MyClass2::someFunction(bool verbose) {
std::cout << "This is new implementation for virtual method " << std::endl;
}