C++ inheritance and same funciton names - c++

I have this situation:
class A
{
public:
A();
virtual ~A();
void doSomething();
};
class B : public A
{
public:
B();
void doSomething(int parameter);
};
If I do the following:
int main()
{
B b;
b.doSomething();
}
It gives me a compile error (no matching function).
How can I solve that without changing the B funcion name? B derives from A so it has also the doSomething() function without parameters. Why is it not working?
Thanks for the help.

Currently, B::doSomething hides A::doSomething.
You might use using to resolve your issue:
class B : public A
{
public:
using A::doSomething;
B();
void doSomething(int parameter);
};

This answer is just an alternative to this solution in case you aren't allowed to modify class B.
If you aren't allowed to modify class B for adding using A::doSomething; inside the class (as already suggested here), you can take a pointer to the member function A::doSomething(), then call it through that member function pointer on the instance b:
auto fptr = &A::doSomething;
B b;
(b.*fptr)();
or simpler, by properly qualifying the member function no member function pointer is needed:
B b;
b.A::doSomething(); // calls A::doSomething()

Related

Using Child on a function with Parent's Typing

I was looking to create a function that is capable of working with any Derived Object of A.
However in this example, I can't seem to be able to use B Object in a function that has a A Typing on it. Is there any way I pass B into the Function?
class A {
public:
A() {
}
};
class B :A {
public:
B() {
}
};
void function(A a) {
return;
}
int main(void) {
B b();
function(b);
}
I've commented on the fixes needed inline:
class A {
public:
A() {}
};
class B : public A { // public inheritance or A will be an inaccessible base of B
public:
B() {}
};
void function(const A& a) { // take a reference to an A to avoid copy-slicing
// ... work with the A part of the object you reference with `a`
}
int main() { // void not needed (but not an error as such)
B b; // not a function declaration anymore
function(b);
}
Actually you are lucky. You made two mistakes that caused passing b to the function fail, while in fact without that other mistakes you can pass b to the function but it would do the wrong thing silently.
First the two mistakes: B b(); declares a function. To declare a default constructed B you write B b;. Then B inherits privately, hence you cannot convert a B to an A. Thats what the error your code causes have told you.
However, after fixing those (and removing user declared constructors taht shouldnt be there when they do nothing)...
class A {};
class B : public A {};
void function(A a) {}
int main(void) {
B b;
function(b); // object slicing !!
}
This code compiles without errors, but usually it does the wrong thing!
Any B can be converted to an A because the inheritance is public, but what happens is object slicing: What is object slicing?. If B had any members not in A then they would all be lost when passing it to function. Its not an issue here because neither A nor B have any members, but in general you want to avoid objects to get sliced.
TL;DR: References / pointers are needed for polymorphism. Pass by (const) reference:
void function(const A& a) {} // does not modify a
void function(A& a) {} // modifies a

Explicitly stop late binding

If we create an object pointer to base class class which points to its child class object then we use virtual key word for late binding
So.,in case of late binding,, our code goes like this :-
#include<iostream>
using namespace std;
struct A{
virtual void print() {
cout<<"function1";
}
};
struct B : public A{
void print(){
cout<<"function2";
}
};
struct C : public B{
void print(){
cout<<"function3";
}
};
int main(){
A* a = new C();
A* p = new B();
a->print();
p->print();
}
Now my question is : when we use virtual keyword in base class, all the functions of derived classes created in base class will become virtual.
In multilevel inheritance, is there any way so that we can stop the function of class c from being virtual??
Any way to break this chain of virtual functions ?
Sorry for any mistakes in question but i tried my best.. ☺️☺️
It is not possible to make a function that is already virtual be not virtual in a child class.
Virtuality is a property of the top-level base class, not the child classes. Once a method has been marked as virtual, and pointer to that class must use dynamic dispatch for that function when calling because the pointer could be pointing to a child class that has overridden the behaviour.
Consider this code:
A a;
B b;
C c;
A * ap = &a;
A * bp = &b;
A * cp = &c;
ap->print(); // 'function1'
bp->print(); // 'function2'
cp->print(); // 'function3'
Here, the calls to print cannot tell which function to call at compile time, they absolutely must use dynamic dispatch.
However, you can make C::print behave like A::print
struct C : public B {
void print() {
A::print();
}
};
Which results in:
ap->print(); // 'function1'
bp->print(); // 'function2'
cp->print(); // 'function1'
And if the behaviour of A::print() changes, C::print() mirrors those changes.
This will still be overridable though, unless you use the final keyword as outlined below.
Original answer:
I believe you are looking for the final specifier.
It's only available as of C++11 though.
To quote en.cppreference's page about the final specifier:
When used in a virtual function declaration or definition, final
ensures that the function is virtual and specifies that it may not be
overridden by derived classes. The program is ill-formed (a
compile-time error is generated) otherwise.
And a variation of the example they give, demonstrating the solution to your problem:
struct A
{
virtual void foo();
};
struct B : A
{
void foo() final; // B::foo is overridden and it is the final override
};
struct C : B
{
void foo() override; // Error: foo cannot be overridden as it's final in B
};

Why am I getting undefined type error after a forward-declaration?

I'm using this code in C++ CLI. However this shouldn't make any difference from C++.
I'm looking for a solution to get rid of that error.
Code :
ref class B;
ref class A;
public ref class A
{
public:
A() {}
B^ b;
void HelloFromA(){
b->HelloFromB();
}
};
public ref class B
{
public :
A^ a;
B() {}
void HelloFromB(){
a->HelloFromA();
}
};
You need to move the bodies of the functions that invoke member functions on the forward-declared classes outside of the headers, to places where definitions are available:
void A::HelloFromA(){
b->HelloFromB();
}
Otherwise, the compiler knows that B is available, but it does not know that B has the HelloFromB member function that takes no arguments.

C++ compile time polymorphism doubt?

Below program contains two show() functions in parent and child classes, but first show() function takes FLOAT argument and second show() function takes INT argument.
.If I call show(10.1234) function by passing float argument, it should call class A's show(float a) function , but it calls class B's show(int b).
#include<iostream>
using namespace std;
class A{
float a;
public:
void show(float a)
{
this->a = a;
cout<<"\n A's show() function called : "<<this->a<<endl;
}
};
class B : public A{
int b;
public:
void show(int b)
{
this->b = b;
cout<<"\n B's show() function called : "<<this->b<<endl;
}
};
int main()
{
float i=10.1234;
B Bobject;
Bobject.show((float) i);
return 0;
}
Output:
B's show() function called : 10
Expected output:
A's show() function called : 10.1234
Why g++ compiler chosen wrong show() function i.e class B's show(int b) function ?
If you have a function in a derived class that has the same name as a function in the base class, it hides all of the functions in the base class. You either need to rename your function, or use a using declaration in your derived class:
using A::show;
or, you can explicitly call the base class function:
Bobject.A::show(i);
There is no polymorphism involved here. You should declare your functions virtual to make them polymorphic, and make them have the same signature.
Use a using declaration.
class B : public A{
int b;
public:
using A::show;
…
};
You're mixing things:
If you had 2 functions in class A with the following signatures:
void Show(int a);
void Show(float a);
Then the compiles would have chosen the "correct" function.
When you define a name in a derived class, it hides the name from the base class.
You can achieve what you want by adding this to B's definition:
using A::show;
That will let you use both A's show() and B's show().

C++ member function virtual override and overload at the same time

If I have a code like this:
struct A {
virtual void f(int) {}
virtual void f(void*) {}
};
struct B : public A {
void f(int) {}
};
struct C : public B {
void f(void*) {}
};
int main() {
C c;
c.f(1);
return 0;
}
I get an error that says that I am trying to do an invalid conversion from int to void*. Why can't compiler figure out that he has to call B::f, since both functions are declared as virtual?
After reading jalf's answer I went and reduced it even further. This one does not work as well. Not very intuitive.
struct A {
virtual void f(int) {}
};
struct B : public A {
void f(void*) {}
};
int main() {
B b;
b.f(1);
return 0;
}
The short answer is "because that's how overload resolution works in C++".
The compiler searches for functions F inside the C class, and if it finds any, it stops the search, and tries to pick a candidate among those. It only looks inside base classes if no matching functions were found in the derived class.
However, you can explicitly introduce the base class functions into the derived class' namespace:
struct C : public B {
void f(void*) {}
using B::f; // Add B's f function to C's namespace, allowing it to participate in overload resolution
};
Or you could do this:
void main()
{
A *a = new C();
a->f(1); //This will call f(int) from B(Polymorphism)
}
Well I think first of all you did not understand what virtual mechanism or polymorhism. When the polymorphism is achieved only by using object pointers. I think you are new to c++. Without using object pointers then there is no meaning of polymorphism or virtual keyword use base class pointer and assign the desired derived class objects to it. Then call and try it.