passing derived object as base class reference parameter - c++

This examples shows a derived class object being passed to a function which takes reference to base class as the parameter. Member function g(int) in the derived class hides the g(float) in the base class. I understand that and my question is not related to it.
class Base {
public:
virtual void g(float x) throw()
{
cout << "Base::g(float)\n";
}
};
class Derived : public Base {
public:
virtual void g(int x) throw() // Bad: Hides Base::g(float)
{
cout << "Derived::g(int)\n";
}
};
void sampleTwo(Base& b, Derived& d)
{
b.g(3.14f);
d.g(3.14f); // Bad: Converts 3.14 to 3 and calls Derived::g(int)
}
int main()
{
Derived d;
sampleTwo(d, d);
return 0;
}
Output is:
Base::g(float)
Derived::g(int)
My question is with the output "Base::g(float)". Since the object referenced by 'b' in sampleTwo() is derived object, shouldn't the dynamic binding call the g() method of the derived class (converting float to int) ?

g(int) and g(float) are two completely different methods. Derived::g(int) does not override Base::g(float). These methods are unrelated.
Since Derived does not override g(float), your expectations about b.g(3.14f) are unfounded. As expected, b.g(3.14f) should call Base::g(float).
If you override g(float) in Derived, then b.g(3.14f) will indeed call Derived::g(float).

Dynamic dispatch invokes the final overrider. Since Derived::g hides rather than overrides Base::g, the final overrider of Base::g in Derived is still Base::g.

g(float) and g(int) are different function members. If you want Derived to work, you have to use g(float) in both classes.
g() can be overloaded check out function overloading:
https://en.wikipedia.org/wiki/Function_overloading
Example (g(float) and g(int) in the same class and separate functions):
class Derived : public Base {
public:
void g(float x) throw();
void g(int x) throw();
};

Related

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

Cast derived virtual override to base pure virtual member

I understand why you cannot simply cast a derived class member function pointer to base class member function pointer as explained here.
But, given this snippet:
struct base
{
virtual void foo() = 0;
};
struct derived : base
{
void foo() override {};
};
struct invoker
{
typedef void(base::*target)();
invoker(base* b, target t)
{
(b->*t)();
}
};
template<typename B, typename D>
void (B::*cast(void (D::*method)()))()
{
return static_cast<void(B::*)()>(method);
}
derived d;
invoker bad(&d, &derived::foo); //C2664
invoker good(&d, cast<base>(&derived::foo));
I wanted to ask is it possible to decorate the base function signature so that compiler understands it is a pure virtual method and and it will be implemented somewhere across the hierarchy (otherwise I could not construct an object of type B)? I understand why I can't do this with normal functions, but IMHO in case of a pure virtual function the compiler has a guarantee it will be implemented (in case it was not done I would get an error about the class B not about the cast).
There's no need to manipulate the type of &derived::foo. One can just use &base::foo instead.
Pointers to member functions respect virtuality. This call
base* pBase = new derived;
auto pFoo = &base::foo;
(pBase->*pFoo)();
will actually call derived::foo, exactly like a simple call pBase->foo() would.
Even if there's a guarantee that it's implemented, it might use additional data members declared only in derived. A possible solution is to use function pointers and pass this as the first parameter (this also shows you why you cannot do it via virtual).
Consider the following diamond hierarchy:
struct base {
virtual void foo() = 0;
};
struct D1 : public virtual base {
virtual void foo() override;
};
struct D2 : public virtual base {
virtual void foo() override;
};
struct Derived : public virtual D1, D2 {
virtual void foo() final;
};
Now consider a scenario where a upcast is allowed from Derived::* to base::* . Which function should be invoked? The compiler loses information about which of D1::foo, D2::foo or Derived::foo you wish to call since that information has been cast away. To avoid this sort of ambiguity such an upcast is disallowed.

Understanding Inheritance and functions with different signatures

Say I have a base class and a derived class.
class Base {
public:
void A(int x, int y) {do something}
void B() {
A(x,y);
do something;
}
};
class Derived : public Base {
void A() {do something else};
};
Derived derived1;
derived1.B();
The signatures of the functions are different, will the B call the derived A or the base A? Iif it will call the derived B, I guess it will dismiss the parameters?
what if the derived A needed different parameters rather than no parameters, would I have to copy B's entire code into the derived class just to change the way B calls A?
A function's code is always evaluated in the context of the class in which it is defined. This includes determining which function each expression calls. So inside Base::B(), the call A(x, y) is translated by the compiler as a call to Base::A. Even if you later call derived1.B(), it will call derived1 . Base::A (pseudo-syntax).
The only thing which changes this slightly is virtual functions. However, even with them, the rules are similar. Overload resolution (which is basically the process of matching a function name & signature to a call expression) is done in the context of the class where the containing function is defined. If the resolution leads to a virtual function being selected, the virtual call mechanism will then be invoked at runtime to call the appropriate override of that function.
Let's consider this example:
struct Base {
virtual void foo(int);
virtual void bar() { foo(0.0); }
};
struct Derived : Base {
virtual void foo(int);
virtual void foo(double);
};
Derived d;
d.bar();
Even in this example, calling d.bar() will call Derived::foo(int). That's because the call-to-signature matching was done in the context of Base, which only sees foo(int) and employs the implicit conversion from double to int.
Two reasons force Base::B to call Base::A not Derived::A
It's calling A with specific overload: A(int, int)
Base::A and Base::B are not virtual, so it calls Base::A. The code is not polymorphic.
The simplest example to show a how a virtual method works is:
class Base {
public:
virtual void A() {
// do job #1
}
};
class Derived : public Base {
public:
virtual void A() {
// do job #2
}
};
// ...
Derived derived1;
Base *base = &derived1;
base->A(); // <---- It calls `Derived::A()` and does job #2
But, if you write A in B with different parameter (overload it), you have to call it explicitly with actual arguments.

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.