how to use a virtual function again in an inherited class - c++

I have 3 classes namely
class A;
class B;
class C : public B {
};
Now i want to use some member functions in C, that have been made virtual in A and have been overridden in B. When I try to access a member of A from C it gives an error saying that C is not a direct base class of A.
What should I do? Should I write that piece of code again?
I searched other sites and got confused answers which ruined my concepts of inheritance, so please give a descriptive but clear answer

Is this what you mean?
class A {
public:
virtual int f() { return 42; }
};
class B : public A {
public:
int f() { return 0; }
};
class C : public B {
public:
int g() { return f(); }
};
There is nothing special to do.

void C::f() { return A::f(); }
Won't this be enough?

Your question isn't very clear. Are you asking how to call A's or B's version of the function? If so, you could do something like this:
#include <iostream>
struct A
{
virtual void Foo () {
std::cout << "A::Foo()" "\n" ;
}
};
struct B : public A
{
void Foo () {
std::cout << "B::Foo()" "\n" ;
}
};
struct C : public B
{
void Foo () {
std::cout << "C::Foo()" "\n" ;
}
};
int main (void)
{
C c ;
c.A::Foo () ;
c.B::Foo () ;
c.Foo () ;
A *p1 = &c ;
p1->Foo () ;
return 0 ;
}
Output:
A::Foo()
B::Foo()
C::Foo()
C::Foo()

What should I do? Should I write that piece of code again?
You can always explicitly refer to methods declared in class A as long they are visible from your inheritance protection scope:
class A {
public:
virtual void foo() {}
};
class B : public A {
public:
virtual void foo() {
// do something else
}
};
class C : public B {
public:
virtual void foo() {
// use A's implementation again
A::foo();
}
};

Related

Access protected member function in C++

There are two external class (A and B)that I cannot change. I would like to access protected member of the class A:: doSomething in C (which I can do edit). Is there any way to access it. I understand its not good practice but I did not find any other way of doing it.
// External code starts
struct A {
friend class B;
protected:
void doSomething() {
std::cout << "A" << std::endl;
}
};
struct B {
protected:
void doSomething() {
A a;
a.doSomething();
}
};
// External code ends
// This will not compile as doSomething is a protected member.
struct C : B {
protected:
void doSomethingElse() {
A a;
a.doSomething();
}
};
Friendship is not transitive, so inheriting from B doesn't help with this.
Inherit from A and form a pointer-to-member to doSomething:
struct Helper : A
{
static constexpr auto ptr = &Helper::doSomething;
};
Use that pointer to call a function on a:
void doSomethingElse()
{
A a;
(a.*Helper::ptr)();
}

Size of derived class in virtual base class function

Consider the following code
class A {
int x, y;
public:
A(){}
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
int a, b, c;
public:
B(){}
};
int main() {
A obja;
B objb;
obja.PrintSize();
objb.PrintSize();
}
The intent of "PrintSize()" is to get the size of the current class where we are calling it from. What happens is that this-keyword refers to class A even though we are calling it from B. We don't want this since we need this function to be general for child classes.
We could obviously redefine the function verbatim to every class. The code would become harder to hande since there's so many unnesessary lines. Not to mention that re-writing the function to every class would defeat the purpose of deriving it in the first place.
Here's my temporary fix:
class A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class C : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class D : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
While the accepted answer may have solved the immediate problem, you suddenly have no common base class for B and C. They inherit from two unrelated classes, namely A<B> and A<C>.
An alternative is to create a common base that defines an interface (called Interface below) and to add the CRTP class template between the derived classes and the interface. This lets you keep pointers and references to Interface and call the virtual member functions using those.
Here's an example of storing pointers to the common base class in a vector:
#include <iostream>
#include <memory>
#include <vector>
struct Interface {
virtual ~Interface() = default;
virtual void PrintSize() const = 0;
virtual void do_stuff() const = 0;
};
template<typename T>
struct Printer : public Interface {
void PrintSize() const override {
std::cout << sizeof(T) << '\n';
}
};
class B : public Printer<B> {
int a{};
public:
void do_stuff() const override { std::cout << "B doing stuff\n"; }
};
class C : public Printer<C> {
int a{}, b{}, c{};
public:
void do_stuff() const override { std::cout << "C doing stuff\n"; }
};
int main() {
std::vector<std::unique_ptr<Interface>> objs;
objs.emplace_back(std::make_unique<B>());
objs.emplace_back(std::make_unique<C>());
for(auto& ptr : objs) {
ptr->do_stuff();
ptr->PrintSize();
}
}
Possible output:
B doing stuff
16
C doing stuff
24
You can use the CRTP idiom to do this.
https://eli.thegreenplace.net/2011/05/17/the-curiously-recurring-template-pattern-in-c
The idea is the parent class is a template, so you can have access to the type of the child class directly in it.
With that, you'll be able to remove all "PrintSize" from child class.
Example :
template <typename Derived>
class A {
int x, y;
public:
A() {}
void PrintSize() { cout << sizeof(Derived) << endl; }
};
class B : public A<B> {
int a, b, c;
public:
B() {}
};
class C : public A<C> {
public:
C() {}
};
int main() {
C objc;
B objb;
objc.PrintSize();
objb.PrintSize();
}
The output is :
8
20

Multiple inheritance in c++ using abstract base classes [duplicate]

I tried this code:
class A
{
virtual void foo() = 0;
};
class B
{
virtual void foo() = 0;
};
class C : public A, public B
{
//virtual void A::foo(){}
//virtual void B::foo(){}
virtual void A::foo();
virtual void B::foo();
};
void C::A::foo(){}
void C::B::foo(){}
int main()
{
C c;
return 0;
}
It is OK when using the commented part, but when I try to write the definitions outside the class declaration, the compiler reports errors.
I am using the MSVC11 compiler, does anyone know how to write this?
I need to move the code into the cpp file.
Thank you~~
A function overrides a virtual function of a base class based on the name and parameter types (see below). Therefore, your class C has two virtual functions foo, one inherited from each A and B. But a function void C::foo() overrides both:
[class.virtual]/2
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.
As I already stated in the comments, [dcl.meaning]/1 forbids the use of a qualified-id in the declaration of a (member) function:
When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers [...]"
Therefore any virtual void X::foo(); is illegal as a declaration inside C.
The code
class C : public A, public B
{
virtual void foo();
};
is the only way AFAIK to override foo, and it will override both A::foo and B::foo. There is no way to have two different overrides for A::foo and B::foo with different behaviour other than by introducing another layer of inheritance:
#include <iostream>
struct A
{
virtual void foo() = 0;
};
struct B
{
virtual void foo() = 0;
};
struct CA : A
{
virtual void foo() { std::cout << "A" << std::endl; }
};
struct CB : B
{
virtual void foo() { std::cout << "B" << std::endl; }
};
struct C : CA, CB {};
int main() {
C c;
//c.foo(); // ambiguous
A& a = c;
a.foo();
B& b = c;
b.foo();
}
You've got just one virtual function foo:
class A {
virtual void foo() = 0;
};
class B {
virtual void foo() = 0;
};
class C : public A, public B {
virtual void foo();
};
void C::foo(){}
void C::A::foo(){}
void C::B::foo(){};
int main() {
C c;
return 0;
}
I stepped into the same problem and accidentially opened a second thread. Sorry for that. One way that worked for me was to solve it without multiple inheritance.
#include <stdio.h>
class A
{
public:
virtual void foo(void) = 0;
};
class B
{
public:
virtual void foo(void) = 0;
};
class C
{
class IA: public A
{
virtual void foo(void)
{
printf("IA::foo()\r\n");
}
};
class IB: public B
{
virtual void foo(void)
{
printf("IB::foo()\r\n");
}
};
IA m_A;
IB m_B;
public:
A* GetA(void)
{
return(&m_A);
}
B* GetB(void)
{
return(&m_B);
}
};
The trick is to define classes derived from the interfaces (A and B) as local classes (IA and IB) instead of using multiple inheritance. Furthermore this approach also opens the option to have multiple realizations of each interface if desired which would not be possible using multiple inheritance.
The local classes IA and IB can be easily given access to class C, so the implementations of both interfaces IA and IB can share data.
Access of each interface can be done as follows:
main()
{
C test;
test.GetA()->foo();
test.GetB()->foo();
}
... and there is no ambiguity regarding the foo method any more.
You can resolve this ambiguity with different function parameters.
In real-world code, such virtual functions do something, so they usually already have either:
different parameters in A and B, or
different return values in A and B that you can turn into [out] parameters for the sake of solving this inheritance problem; otherwise
you need to add some tag parameters, which the optimizer will throw away.
(In my own code I usually find myself in case (1), sometimes in (2), never so far in (3).)
Your example is case (3) and would look like this:
class A
{
public:
struct tag_a { };
virtual void foo(tag_a) = 0;
};
class B
{
public:
struct tag_b { };
virtual void foo(tag_b) = 0;
};
class C : public A, public B
{
void foo(tag_a) override;
void foo(tag_b) override;
};
A slight improvement over adigostin's solution:
#include <iostream>
struct A {
virtual void foo() = 0;
};
struct B {
virtual void foo() = 0;
};
template <class T> struct Tagger : T {
struct tag {};
void foo() final { foo({}); }
virtual void foo(tag) = 0;
};
using A2 = Tagger<A>;
using B2 = Tagger<B>;
struct C : public A2, public B2 {
void foo(A2::tag) override { std::cout << "A" << std::endl; }
void foo(B2::tag) override { std::cout << "B" << std::endl; }
};
int main() {
C c;
A* pa = &c;
B* pb = &c;
pa->foo(); // A
pb->foo(); // B
return 0;
}
Assuming that the base classes A and B are given and cannot be modified.

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.