what is the way of overriding a method in some code - c++

Suppose we have the following code:
class Base
{
public:
virtual void foo() const
{ cout << "In Base::foo\n"; }
}
class Derived : public Base
{public:
virtual void foo()
{ cout << "In Derived::foo\n"; }
}
void main()
{
Base* b = new Derived();
b->foo();
delete b;
}
It will give us the following output: In Base::foo.
Now suppose I want to get - without changing the main function - the follwing output instead the one given above:
In Derived::foo
As far as I understand, I should override the function foo() of in the base, to get the output of the method
foo() in the inheriting class which is class 'Derived'.
But the problem is that in that case I can't using the command override, becuase the method in the base is defined as constant , which in the other class it is not.
So, how should I if then overriding that method ?

In order to override the function void foo() const of the base class, you must declare the function void foo() const in the derived class. You've declared the function void foo() instead (note the lack of const), which doesn't override the function in the base, because it has a different declaration.
So, how should I if then overriding that method ?
Add the missing const qualifier.
P.S. Few other bugs in your program:
main must return int.
Class definitions must end in a semicolon.
Deleting a derived object through a pointer to base has undefined behaviour unless the destructor of the base is virtual.

Related

Why using a different return type in virtual function declaration throws an error instead of resulting in a redefinition?

Base class:
class Base
{
public:
virtual int f() const
{
return 1;
}
};
Derived class:
class Derived: public Base
{
public:
void f() const {}
};
Above code throws a "return type is not identical/covariant error".
I've read few discussions on it. This one is similar but they only say that it will break the code if the return types aren't identical/covariants.
Override a member function with different return type
Why the behavior I'm expecting doesn't happen?
Expected Behavior: The VPTR in Derived points to Base::f() (I've read incase an override isn't provided for a virtual function, Derived objects will just uses the inherited class version ). Also it hides the name f() so now a call like this:
Derived x;
x.f();
should've called Derived::f() and a call like this:
x.Base::f();
should've called the Base::f() function. This doesn't seem like breaking the code.
Incase its upcasted, even then it shouldn't break the code because VPTR for both classes points to the same Base::f()
The only reason I can think of is that such a declaration(same signature and covariant/identical return types) is reserved for overriding virtual methods and we just cannot use it to cause the behavior I'm expecting.
When the compiler encounters the matching signature (arguments, constness), it automatically makes the void f() const declaration virtual. So the definition of Derived is interpreted as:
class Derived: public Base
{
public:
virtual void f() const {} // virtual keyword is added
};
It clearly looks like an attempt to override Base::f(). All this happens because the function signatures match in the Base and Derived class. If the signatures didn't match, then only would this be a redefinition in which case it would've hidden the Base::f() in Derived class.

Polymorphism in C++ why is this isn't working?

class Base {
public:
virtual void f();
void f(int);
virtual ~Base();
};
class Derived : public Base {
public:
void f();
};
int main()
{
Derived *ptr = new Derived;
ptr->f(1);
delete ptr;
return 0;
}
ptr->f(1); is showing the following error: "too many arguments in function call".
Why is this isn't possible? isn't derived inherited all the functions form base and is free to use any of them?
I could call it explicitly and it would work but why isn't this allowed?
What you are seeing is called hiding.
When you override the function void f() in the Derived class, you hide all other variants of the f function in the Base class.
You can solve this with the using keyword:
class Derived : public Base {
public:
using Base::f; // Pull all `f` symbols from the base class into the scope of this class
void f() override; // Override the non-argument version
};
As mentioned by #Some Programming Dude : it is because of Hiding.
To understand hiding in relatively simpler language
Inheritance is meant to bring Baseclass variables / functions in Derived class.
But, on 1 condition : "If its not already available in Derived Class"
Since f() is already available in Derived, it doesn't make sense to look at Base class from compiler perspective.
That's the precise reason why you need to scope clarify while calling this function
void main()
{
Derived *ptr = new Derived;
ptr->Base::f(1);
delete ptr;
}
Suppose for time being that Derived do have the access to the function void Base::f(int);. Then it will be a case of function overloading. But, this is invalid case of function overloading since one function f(int);is in Base and other function f(); is in Derived. Function Overloading happens inside a single class. Function Overriding happens across classes. The example you posted is a case of Name Hiding in Inheritance
"Derived *ptr" This definition will only allow "ptr" to access all the member functions which are defined via Derived class or its child class. But, it will not allow u to access the member functions which are coming in Derived class because of inheritance.
If u want to access base class version of function "f" then use "Base *ptr" and it will choose the correct version of function automatically as shown :)
class Base {
public:
virtual void f()
{
cout<<"Here 2"<<endl;
}
void f(int x)
{
cout<<"Here 1"<<endl;
}
virtual ~Base() {}
};
class Derived : public Base {
public:
void f()
{
cout<<"Here 3"<<endl;
}
virtual ~Derived() {}
};
int main()
{
Base *ptr = new Derived;
ptr->f(1);
delete ptr;
return 0;
}
output is
Here 1

Virtual method causes compilation error in Derived class

Consider the next code :
#include <iostream>
using namespace std;
class A
{
public:
virtual int f() {cout <<"A:: f()\n"; return 1;}
virtual void f(int) {cout <<"A:: f(int)\n";}
virtual void g() {cout <<"A::g()\n";}
};
class B3 : public A
{
public:
void f() {cout <<"B3::f ()\n";}
};
int main()
{
return 0;
}
It produces the following error :
..\main.cpp:17: error: conflicting return type specified for 'virtual void B3::f()'
..\main.cpp:9: error: overriding 'virtual int A::f()'
but why ? in the worst case I'd think I'd have an Hiding case , but instead I get compilation error regarding A's virtual int f() {cout <<"A:: f()\n"; return 1;}
thanks ,Ronen
Don't confuse overriding with hiding. You override virtuals.
Your class definition is equivalent to:
class B3 : public A
{
public:
virtual void f() {cout <<"B3::f ()\n";}
};
Once a function declared virtual, it will remain virtual for all classes deriving from your base class, regardless of whether you explicitly declare it virtual or not. Therefore you are trying to override a virtual function and changing its return type, which is illegal in C++. If the function were not virtual, you would simply be hiding the base class implementation, therefore changing the return type is valid. There would be no ambiguity since the compiler would know where to call the function from and what return type to expect.
However, consider having:
A* a;
....
a->f();
What would a-f() return? a is a pointer to A, but can point to an object of type B3. So it either returns an int or doesn't return anything. See the ambiguity here?
Instead, no polymorphism involved,
A a;
a.f();
will cal f from a, same as b3.f would call f from B3.
All in all, overriding base class functions implies keeping the same return type. If you want to create a new function with a different return type, change its signature (either its name or its parameters - or both).
Anyway, you shouldn't even be doing this... Why would you want to have a function with the same name and no parameters return different things? Wouldn't adding a separate function be more readable?
You'd have hiding if f() would have had a different parameter list, or not declared as virtual on the base class. In the former case, since overloading doesn't cross inheritance borders, A's f would have been hidden. But this is not the case, since you have f() on both classes, which only differ in return value. Return values covariance is the only difference allowed, and since it's not the case (void does not inherit from int), you get the error.

Why is the base class method called if the derived class overrides the method?

consider the following program:
class Base {
public:
virtual void foo() const {
cout << "Base::foo()" << endl;
}
};
class Derived : public Base {
public:
virtual void foo() {
cout << "Derived::foo()" << endl;
}
};
void func(Base& obj) {
obj.foo();
}
void main() {
Derived d;
func(d); // Base::foo() is printed
}
If I remove the const from the Base class foo method then Derived::foo() is called.
I can't seem to understand this behavior.
1) What is the reason for this behavior?
2) Is this decided at compile time or runtime?
Thanks
In the derived class, the function signature is this:
virtual void foo(); //Derived::foo
which doesn't mention const. Its a non-const member function, while the Base::foo is a const member function. They're two different functions, because const is a part of the function signature.
virtual void foo() const; //Base::foo
Derived class does NOT override this function, instead it adds another function.
So the fix is this:
class Derived : public Base {
public:
virtual void foo() const {
cout << "Derived::foo()" << endl;
}
};
As const is a part of the function signature. So you must mention it when you intend to override base's foo.
#davka's asked:
so why the const version is selected over the non-const? Is there any rule or it just happened to be the first option?
Its because the static type of obj is Base, and function name is resolved based on the static type of object. Base doesn't even have non-const version. So there is no question of it being selected or rejected. It doesn't exist in Base to begin with.
void func(Base& obj) {
obj.foo(); //calls Base::foo
}
However, if you change the above code to the following:
void func(Derived & obj) {
obj.foo(); //calls Derived:foo
}
Now non-const version will be selected, because Base::foo is hidden in Derived class.
Since Derived::foo hides the Base::foo, so you cannot call the latter using an instance of Derived.
Now, lets unhide Base::foo and do some more experiments.
class Derived : public Base {
public:
using Base::foo; //<----------------this unhides Base::foo
virtual void foo() {
cout << "Derived::foo()" << endl;
}
};
Now in Derived, both functions (const as well as non-const version) are available, unhidden. Now few interesting questions.
Since now Derived has both functions unhidden, which function will be called in each function below?
void f(Derived& obj) {
obj.foo(); //Which function? Base::foo or Derived::foo?
}
void g(const Derived & obj) {
obj.foo(); //Which function? Base::foo or Derived::foo?
}
First one will call Derived::foo which is non-const version, and second one will call Base::foo which is const version. The reason is simple, with const object, only const functions can be invoked, but with non-const objects, both can be invoked, however non-const version is selected if its available.
See online demo : http://www.ideone.com/955aY
You aren't overriding the method, since Derived::foo isn't exactly the same.
To override a method, the base and overridden versions must be identical, including const-ness.
In C++, you can have two functions with the same name and the same parameters, where the only difference that one is const and one is not.
The idea is that you sometimes want different behaviors. For example, an access function function might have different return types:
class MyClass
{
public:
virtual Xxx * GetXxx();
virtual Xxx const * GetXxx() const;
// ....
}
You can override these functions individually.
In your case, as you call foo from a non-const object, you called the non-const variant of the function. As you had overridden the const-variant, the one in the base class is the one being called.
What you're doing is called "overloading." In overriding, as #SLaks pointed out, the signature needs to be the same.
const is part of the signature. void foo() const is a different function from void foo(). You are not overriding at all. That's why.

Why might my virtual function call be failing?

Update: This issue is caused by bad memory usage, see solution at the bottom.
Here's some semi-pseudo code:
class ClassA
{
public:
virtual void VirtualFunction();
void SomeFunction();
}
class ClassB : public ClassA
{
public:
void VirtualFunction();
}
void ClassA::VirtualFunction()
{
// Intentionally empty (code smell?).
}
void ClassA::SomeFunction()
{
VirtualFunction();
}
void ClassB::VirtualFunction()
{
// I'd like this to be called from ClassA::SomeFunction()
std::cout << "Hello world!" << endl;
}
The C# equivalent is as follows: Removed C# example, as it's not relevant to the actual problem.
Why isn't the ClassB::VirtualFunction function being called when called from ClassA::SomeFunction? Instead ClassA::VirtualFunction is being called...
When I force implementation of the virtual function ClassA::VirtualFunction, like so:
class ClassA
{
public:
virtual void VirtualFunction() = 0;
void SomeFunction();
}
class ClassB : public ClassA
{
public:
void VirtualFunction();
}
void ClassA::SomeFunction()
{
VirtualFunction();
}
void ClassB::VirtualFunction()
{
// I'd like this to be called from ClassA::SomeFunction()
std::cout << "Hello world!" << endl;
}
The following error occurs at runtime, despite the derrived function deffinately being declared and defined.
pure virtual method called
terminate called without an active exception
Note: It seems like the error can be caused even by bad memory usage. See self-answer for details.
Update 1 - 4:
Comments removed (not releavnt).
Solution:
Posted as an answer.
class Base {
public:
virtual void f() { std::cout << "Base" << std::endl; }
void call() { f(); }
};
class Derived : public Base {
public:
virtual void f() { std::cout << "Derived" << std::endl; }
};
int main()
{
Derived d;
Base& b = d;
b.call(); // prints Derived
}
If in the Base class you do not want to implement the function you must declare so:
class Base {
public:
virtual void f() = 0; // pure virtual method
void call() { f(); }
};
And the compiler won't allow you to instantiate the class:
int main() {
//Base b; // error b has a pure virtual method
Derived d; // derive provides the implementation: ok
Base & b=d; // ok, the object is Derived, the reference is Base
b.call();
}
As a side note, be careful not to call virtual functions from constructors or destructors as you might get unexpected results.
If you're getting that 'pure virtual method called
terminate called without an active exception' error message, that means you're calling the virtual function from the constructor or destructor of classA (the base class), which you should not do.
on the pure virtual method called error:
You should create a different question as it is in fact different than the other. The answer to this question is on the very last paragraph of my previous answer to your initial question:
Do not call virtual functions from constructors or destructors
class Base
{
public:
Base() { f(); }
virtual void f() = 0;
};
class Derived : public Base
{
public:
virtual void f() {}
};
int main()
{
Derived d; // crashes with pure virtual method called
}
The problem in the code above is that the compiler will allow you to instantiate an object of type Derived (as it is not abstract: all virtual methods are implemented). The construction of a class starts with the construction of all the bases, in this case Base. The compiler will generate the virtual method table for type Base, where the entry for f() is 0 (not implemented in base). The compiler will execute the code in the constructor then. After the Base part has completely been constructed, construction of the Derived element part starts. The compiler will change the virtual table so that the entry for f() points to Derived::f().
If you try calling the method f() while still constructing Base, the entry in the virtual method table is still null and the application crashes.
When A calls VirtualFunction() it will automatically call the version on B. That is the point of virtual functions.
I am not as familiar with the C++ syntax tho. Do you have to declare the function to be virtual at the point of the body as well as in the header?
Alsop, in class B you probably need to mark it as override
in C# its easy. I just don't know the c++ syntax.
public class ClassA
{
public **virtual** void VirtualFunction(){}
public void FooBar()
{
// Will call ClassB.VirtualFunction()
VirtualFunction();
}
}
public class ClassB
{
public **overide** void VirtualFunction()
{
// hello world
}
}
If you want to force the derived classes to implement the VirtualFunction:
class ClassA
{
public:
virtual void VirtualFunction()=0;
void SomeFunction();
}
This is C++. Default the derived function will be called.
If you want to call the base-class function do:
void ClassA::SomeFunction()
{
// ... various lines of code ...
ClassA::VirtualFunction();
}
There's nothing wrong with your code but your sample is incomplete. You do not state where you are calling SomeFunction from.
As has already been pointed out by dribeas you must be careful calling virtual functions from your constructor as the virtual tables are only built up as each class in the hierarchy completes construction.
Edit: The following paragraph of my reply was incorrect. Apologies. It is fine to call SomeFunction from the constructor of ClassB as the vtable is in place (at least) by the end of the initialiser list i.e. once you are in the body of the constructor. It is not fine to call it from ClassA's constructor of course.
Original paragraph:
I suspect you must be calling SomeFunction from the constructor of ClassB at which point only the vtable up to type ClassA will be complete i.e. to the virtual dispatch mechanism your class is still of type ClassA. It only becomes an object of type ClassB when the constructor completes.
To call a virutal function function you need to call via a pointer or a reference.
void ClassA::SomeFunction()
{
VirtualFunction(); // Call ClassA::VirtualFunction
this->VirtualFunction(); // Call Via the virtual dispatch mechanism
// So in this case call ClassB::VirtualFunction
}
You need to be able to distinguish the two different types of call otherwise the classA::VirtualFunction() becomes inaccessible when it is overridden.
As pointed out by others if you want to make the base class version abstract then use the = 0 rather than {}
class A
{
virtual void VirtualFunction() =0;
....
But sometimes it is legitimate to have an empty definition. This will depend on your exact usage.
You aren't defining the function in ClassB correctly, it should be:
public class ClassB
{
public void override AbstractFunction()
{
// hello world
}
}
Then, any call from the base class to virtual/abstract methods will call the implementation on the derived instance.