Virtual function does not overrides to latest inheriting object - c++

I have 3 classes: A, B, C. B inherits from A, and C inherits from B (so C is grandchild of A).
Every object has function talk() that displays text, in A and B it's virtual.
Let have outside function call(A &a), that takes object A by reference, and calls function talk().
Sending object C to the function, it uses talk() from B instead of C, even that at B talk() is virtual.
Why it is so? How to make it call version from C?
#include <iostream>
using namespace std;
class A {
public:
virtual void talk() = 0;
virtual void say() = 0;
};
class B : public A {
public:
virtual void talk() // Why C does not overrides this?
{ cout << "hello\n"; }
};
class C : public B {
public:
void talk (int a) // It should override B.talk();
{ cout << "bye\n";}
virtual void say() { cout << "my name\n"; }
};
void call(A &a) {
a.talk(); // Why does it call virtual talk() from B rather than from C?
a.say(); // This was found so it knows about object C
}
int main() {
C c;
call(c);
system("PAUSE");
return 0;
}
I'd expect that call(A &a) takes the furthest inheritance version if every class between has virtual talk()

In your example, C.talk(int) doesn't override B.talk() because C.talk takes an int as a parameter, so it's an entirely different function.
You can add override after a function declaration to get the compiler to check if it actually overrides anything:
class C : public B {
public:
// Here, the compiler complains because there's no talk(int) method
// That it can override
void talk (int a) override;
{ cout << "bye\n";}
virtual void say() { cout << "my name\n"; }
};

Related

How do I choose the base class when overriding a function in c++?

I have two base classes and a class that inherits both base classes.
Both base classes have a virtual function with the same signature, and I want to provide different implementations in the derived class to each virtual function.
class A{
virtual void f() = 0;
}
class B{
virtual void f() = 0;
}
class Derived:public A, public B{
void A::f() override{ // Error
...
}
void B::f() override{ // Error
...
}
}
What is the correct way to do this? (I cannot rename the virtual function. Actually the two base classes are generated from the same template class.)
template <typename T>
class AShim : public A {
void f() override {
static_cast<T*>(this)->A_f();
}
};
template <typename T>
class BShim : public B {
void f() override {
static_cast<T*>(this)->B_f();
}
};
class Derived: public AShim<Derived>, public BShim<Derived> {
void A_f();
void B_f();
};
class A {
public:
virtual void f() = 0;
};
class B {
public:
virtual void f() = 0;
};
class Derived :public A, public B {
public:
void A::f() {
cout << "Inside A's version"<<endl;
}
void B::f() {
cout << "Inside B's version"<<endl;
}
};
int main()
{
Derived derived;
cout << "calling A" << endl;
A *a;
a = &derived;
a->f();
cout << "calling B" << endl;
B *b;
b = &derived;
b->f();
}
Works fine for me. No need to explicitly mention override keyword as pure virtual functions will be overridden by virtue of its default properties.Use base class's scope while defining the functions as you have already done. Use public access specifier to enable derived classes to override the pure virtual function. That's all.

Can I do/mimic things likes this (partial override) in C++?

I have two classes A and B, both defining method m(). Although the signatures of these methods are the same, they are two totally different methods with different meanings. In class C, I want to update both m(). Instead of writing a new m() in class C that fuses the two m() from A and B, I want to override them separately. See the following code:
class A { public: virtual void m() {cout << "MA" << endl;}};
class B { public: virtual void m() {cout << "MB" << endl;}};
class C : public A, public B {
public: virtual void m() update A {cout << "MA2" << endl;}};
public: virtual void m() update B {cout << "MB2" << endl;}};
}
void func(A* a) { a->m(); }
int main() {
C* c = new C();
c->B::m(); //print "MB2"
func(c); //print "MA2"
return 0;
}
I know that the update syntax is not supported in C++, but is there any workaround to simulate this in C++?
A nasty part of multiple inheritance is that indeed there is only one m in C that overrides both. You need a middle-man class to disambiguate the call in case of 2 or more classes that define m. Fortunately, you can use a template in order to automate the process:
template<class C>
class MiddleMan : public C {
void m() override final { m_impl(this); }
protected:
virtual void m_impl(MiddleMan*) = 0;
};
Now you just use this template and override the new functions it adds:
class C : public MiddleMan<A>, public MiddleMan<B> {
private:
void m_impl (MiddleMan<A>*) override {cout << "MA2" << endl;}
void m_impl (MiddleMan<B>*) override {cout << "MA2" << endl;}
};
The implementation of m in each middle man class will call the new virtual functions that are overloaded. You then define these overloads. I used MiddleMan* as the extra parameter which facilitates overloading, but any type which is cheap to pass by value and depends on the template parameter will do for disambiguation.
You just cannot do that, for the same reason in C you can't have two functions with the same name: the compiler would not know which one to call!
To get the same effect that you want, I'd change your code to look as follows:
class A { public: virtual void ma() {cout << "MA" << endl;}};
class B { public: virtual void mb() {cout << "MB" << endl;}};
class C : public A, public B {
public: virtual void ma() override {cout << "MA2" << endl;} // these are *extra*: };
public: virtual void mb() override {cout << "MB2" << endl;} // these are *extra*: };
}
void func(A* a) { a->ma(); } // the problem here with a->m() would be
// that the compiler would not know which m() function to call --
// you basically want two pointers *crammed* somehow in the same vfptr entry,
// and the compiler to *automagically* know which one to call,
// depending on... unspecified conditions!
int main() {
C* c = new C();
c->B::m(); //this will never print "MB2" in your code;
//it will always print "MB", no matter what you do!
c->mb(); //print "MB2"
func(c); //print "MA2"
return 0;
}
I know, this may not be the answer you're looking for, but then you have to describe your problem better. In my opinion, this is a valid solution to your problem, as it's currently described.

c++ multi inheritence order and virtual functions

Does it important in which order you inheritence abstact classes, which has same functions ?
class A {
public:
virtual void f1() = 0;
virtual void f2() = 0;
};
class B : public A {
public:
virtual void f1() { globalF1_B(); }
virtual void f2() { globalF2_B(); }
};
class C : public A {
public:
virtual void f1() { globalF1_C(); }
};
class D : public A, public B, public C { };
class E : public A, public C, public B { };
Does D and E classes would be the same, if I would write it like below:
class D{
public:
virtual void f1() { globalF1_C(); }
virtual void f2() { globalF2_B(); }
};
class E {
public:
virtual void f1() { globalF1_B(); }
virtual void f2() { globalF2_B(); }
};
PS. I inheritence class A into class D and class E just in case I can forget make some realization of class A's function.
No there are not the same. Besides an invalid C++ code provided, we can say :
In the first case your classes D and E have two method f1() (one inherited from B and one inherited from C) and one method f2() (inherited from C). If you would be able to construct a D object name d, then d.f1() would be reported as an ambiguity that you would need to clarify either this way : d.B::f1() or this one d.C::f1().
While in the second case your classes will only have two methods f1() and f2().
#include <iostream>
using namespace std;
class A {
public:
virtual void f1() = 0;
virtual void f2() = 0;
};
class B : public A {
public:
virtual void f1() { cout << "B::f1()" << endl; }
virtual void f2() { cout << "B::f2()" << endl; }
};
class C : public A {
public:
virtual void f1() { cout << "C::f1()" << endl; }
virtual void f2() { cout << "C::f2()" << endl; }
};
class D : public B, public C { };
class E : public C, public B { };
int main() {
D d;
// d.f1(); // t.cpp:28:5: error: member 'f1' found in multiple base classes of different types
d.C::f1();
d.B::f1();
}
NO, the first version of D & E won't compile either. there would be ambiguity in resolving f1 and f2 in D and E

How to deal with name hiding when base class function already overloaded with different access

Class foo act as interface, it has a pure virtual function and also provide some public overloaded function with same name for convenience so that derived class won't need to provide them in every implementation.
But since derived class must override the pure virtual function, it hides foo's public function.
I tried with "using foo::A", but it won't work because "using" will bring all function including the private one and result in compiler error "error C2876: 'foo' : not all overloads are accessible".
class foo
{
private:
virtual void A(int a)=0;
public:
void A()
{
A(1000);
}
void A(int a, int b)
{
A(a+b);
}
};
class bar : public foo
{
private:
virtual void A(int a)
{
cout << a << "\n";
}
};
int main()
{
bar x;
x.A();
return 0;
}
I know I can redefine every overloaded function in every class which derived from foo, but this defeat the purpose of convenience.
Or I can cast bar to foo before calling A(), but this approach will get confused since I need to remember which function is define in which class. For example:
class foo
{
private:
virtual void A(int a)=0;
public:
void A()
{
A(1000);
}
void A(int a, int b)
{
A(a+b);
}
};
class bar : public foo
{
private:
virtual void A(int a)
{
cout << "bar:" << a << "\n";
}
public:
void A(int a, int b, int c)
{
A(a+b+c);
}
};
class foobar : public bar
{
private:
virtual void A(int a)
{
cout << "foobar:" << a << "\n";
}
};
int main()
{
foobar x;
x.foo::A();
x.bar::A(1,2,3);
return 0;
}
I need to clearly remember A withouth argument come from foo, and A with three arguments come from bar. This is also not good for convenience.
When using the non virtual interface idiom, it's safer, and more explicit, to name the two functions (the public non-virtual and the private virtual) differently.
This shows well what the code does, and would solve your problem:
class foo
{
private:
virtual void doA(int a)=0;
public:
void A()
{
doA(1000);
}
void A(int a, int b)
{
doA(a+b);
}
};
And of course don't forget to change in the hierarchy.

Is it function overloading or overriding?

Is it function overloading or overriding or something else ? ( hello function )
class A {
public:
void hello(int x) { cout << "A" << endl; }
};
class B : public A {
public:
void hello() { cout << "B" << endl; }
};
void main() {
B obj;
obj.hello();
}
It's neither, it's function hiding.
Declaring a non-virtual function with the same name (even if the signature is different) in a derived class hides the base class implementation completely.
To still have access to A::hello, you can do the following:
class B : public A {
public:
using A::hello;
void hello() { cout << "B" << endl; }
};
Overriding:
struct A
{
virtual void foo() {}
};
struct B : public A
{
/*virtual*/ void foo() {}
};
Overloading:
struct A
{
void foo() {}
void foo(int) {}
};
Overriding:
struct Base {
virtual void Foo() { std::cout << "Base\n"; };
};
struct Derived : Base {
virtual void Foo() { std::cout << "Derived\n"; };
// same name and signature as a virtual function in a base class,
// therefore this overrides that function. 'virtual' is optional in
// the derived class (but you should use it).
};
C++11 adds a way to ensure your function overrides:
struct Derived : Base {
virtual void Foo() override { std::cout << "Derived\n"; };
};
Now if the method Foo is not overriding something then you will get an error.
struct Base {
void Foo();
};
struct Derived : Base {
virtual void Foo() override; // error, Derived::Foo is hiding Base::Foo, not overriding
};
This is neither.
Overriding is a function with the same signature (same name, parameters and return value) in a subclass. Overloading is a function with the same name but different parameters.
It is not Overloaded Function because in Function Overloading either number of parameters or type of parameters should differ.For example :
void show(int a,int b);
void show(int a);
void show(char a,char b);
And neither it is Function Overriding because in Overridden function prototype must be same.For example :
Base class and Derived class having function
void show();
//function prototype must be same