Overriding a virtual function with optional arguments - c++

Why is this printing 23 as output; my expectation was 33. Could somebody please shed some light on this.
struct A {
virtual void f() {cout << "1";}
};
/* Private inheritance */
struct B : private A {
void f(int x = 0) {cout << "2";}
};
struct C : B {
void f(){cout << "3";}
};
int main() {
C obj;
B &ref = obj;
ref.f();
obj.f();
}

The f(int x = 0) method in the B struct does not share a signature with either the A nor C struct's f() methods.

Related

C++ Polymorphism : Is it possible to use a function from a double derived class into the base class?

I'm new to polymorphism and I'm trying to learn how this exactly works .
I want for example to get the print() function of class Y and use it in the base class .
Is this possible to do ?
class A
{
public:
A() = default;
virtual void print()
{
//Is it possible to get the print() function of class Y here ?
};
};
class B : public A
{
public:
B() = default;
void print(){ std::cout << "B " << std::endl;}
};
class C : public A
{
public:
C() = default;
void print(){ std::cout << "C " << std::endl;}
};
class Y : public C , public B
{
public:
Y() = default;
void print()
{
B::print();
C::print();
}
};
int main()
{
A a;
a.print();
return 0;
}
Your main() is creating an A object directly, not a Y object. That is why you are not seeing the output you want. Polymorphism only works when accessing derived class objects via base class pointers/references, eg:
int main()
{
Y y;
A *a = static_cast<C*>(&y);
a->print();
return 0;
}
int main()
{
Y y;
A &a = static_cast<C&>(y);
a.print();
return 0;
}
The reason for the type cast is becauseY has 2 A portions, one from B and one from C, so you have to help the compiler a little by specifying which A you want to point to.

How can I omit a class inheritance?

I'm trying to find my way around. I have two classes, A and B, where B inherits from A.
There are also two overloaded functions for A and B, that act on them in two different ways.
Now call these functions from a class function like this:
#include <iostream>
struct A;
struct B;
void f(A a);
void f(B b);
struct A {
int i;
A(): i(0) {};
void thisf() { f(*this); }
};
struct B: public A {
int j;
B(): j(1) {};
void thisf() { f(*this); }
};
void f(A a) { std::cout << a.i << std::endl; }
void f(B b) { std::cout << b.i << " " << b.j << std::endl; }
int main() {
A a;
B b;
a.thisf();
b.thisf();
return 0;
}
My question is: since A::thisf() and B::thisf() are the same (and will stay the same for more subclasses), is there a way how I can omit B::thisf() while still having the same functionality?
The expected output should look like:
0
0 1
More detail why I try to do this: I want to provide some custom render functionality to different kinds of data without bloating the class with render logic and have a separate render class with some state variables. But I don't want to give up the possibility to write
b.render()
in some situations. In my class definitions I want to spare every line I can.
I got the idea in this thread: https://gamedev.stackexchange.com/questions/63912/visitor-pattern-vs-inheritance-for-rendering
In your proposed problem you claim the need for a method in A and B that is not polymorphic and yet exhibits different behaviour in the two classes (linked by inheritance) with the same signature.
In addition, the method defers to a free function found by ADL (good!).
So... my question to you is this. If you already have the guarantee of a free function called f(A|B), why not simply document that as the interface?
If you insist on having thisf() you are causing yourself a problem because the inheritance relationship will cause B's thisf() to be ambiguous with A's. This can be solved with polymorphism (as per the other answer) but since you're rejecting that, you are are left with few options other than to eliminate the logically redundant thisf() altogether.
in any case, this code will do exactly as you want:
#include <iostream>
struct A;
struct B;
void f(A a);
void f(B b);
struct common_interface {
virtual void thisf() = 0;
};
template<class Host, class Base>
struct common_interface_impl : Base {
virtual void thisf() {
f(static_cast<Host&>(*this));
}
};
struct A : common_interface_impl<A, common_interface>
{
int i;
A(): i(0) {};
};
struct B: common_interface_impl <B, A>
{
int j;
B(): j(1) {};
};
void f(A a) { std::cout << a.i << std::endl; }
void f(B b) { std::cout << b.i << " " << b.j << std::endl; }
int main() {
A a;
B b;
a.thisf();
b.thisf();
return 0;
}
#include <iostream>
struct A {
int i;
A(): i(0) {};
virtual ~A() {};
virtual void thisf() { std::cout << i << std::endl; }
};
struct B: public A {
int j;
B(): j(1) {};
void thisf() { A::thisf(); std::cout << j << std::endl; }
};
void f( A* a )
{
a->thisf();
}
int main() {
A* a = new A();
A* b = new B();
f( a ); f( b );
delete a; delete b;
return 0;
}

how to use a virtual function again in an inherited class

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();
}
};

c++ Virtual/Non-virtual Diamond inheritance

Given the following code in C++:
struct A {
A() { f(0); }
A(int i) { f(i); }
virtual void f(int i) { cout << i; }
};
struct B1 : virtual A {
B1(int i) : A(i) { f(i); }
virtual void f(int i) { cout << i+10; }
};
struct B2 : virtual A {
B2(int i) : A(i) { f(i); }
virtual void f(int i) { cout << i+20; }
};
struct C : B1, virtual B2 {
int i;
C() : B1(6),B2(3),A(1){}
virtual void f(int i) { cout << i+30; }
};
Can someone explain why C* c = new C(); will print 1 23 and then 16 in that order? How does it decide which order to print in? I know that the nonvirtual B1 will be called last but why is A() called first? Thanks for the help and explanation ahead of time.
Because your are virtually inheriting B2, the compiler will construct it first as to identify which variables are virtually inherited in C before it constructs any non-virtual inheritance (B1). Of course, A gets constructed first because B2 needs it before it can be constructed.

C++ override function of object created by subclass

I was wondering if it's possible to override just one function in a class without creating an entirely new class.
I would like bObj1.foo(); to output "foo!" and bObj2.foo() to output "foo?", but currently they both output "foo!".
#include <iostream>
using namespace std;
class B {
public:
virtual void foo() { cout << "foo!" << endl; }
};
class A {
public:
B f();
};
B A::f() {
B bObj;
return bObj;
}
class C : public A {
};
int main()
{
A aObj;
B bObj1 = aObj.f();
bObj1.foo(); // "foo!"
C cObj;
B bObj2 = cObj.f();
bObj2.foo(); // "foo?"
}
You can get the behavior that you want with a simple change, which consists in moving the "virtual" behavior to the A and C classes.
Here I modified your application to return the expected result:
#include <iostream>
using namespace std;
class A;
class B {
public:
B(A& a) : aref(a) {}
void foo();
private:
A& aref;
};
class A {
public:
B f();
virtual void foo() { cout << "foo!" << endl; }
};
B A::f() {
B bObj(*this);
return bObj;
}
class C : public A {
public:
virtual void foo() { cout << "foo?" << endl; }
};
void B::foo() { aref.foo(); }
int main()
{
A aObj;
B bObj1 = aObj.f();
bObj1.foo(); // "foo!"
C cObj;
B bObj2 = cObj.f();
bObj2.foo(); // "foo?"
}
In order to change the virtual function, you have to create a new type - there's no way around that in C++. However, an alternate mechanism - function objects - may do what you want here.
#include <functional>
#include <iostream>
using namespace std;
class B {
public:
B(function<void ()> foo_impl) : foo_impl(foo_impl) {}
void foo() {foo_impl();}
private:
function<void()> foo_impl;
};
class A {
public:
virtual B f();
};
B A::f() {
B bObj([](){cout << "foo!" << endl;});
return bObj;
}
class C : public A {
public:
virtual B f() override;
};
B C::f() {
B bObj([](){cout << "foo?" << endl;});
return bObj;
}
int main()
{
A aObj;
B bObj1 = aObj.f();
bObj1.foo(); // "foo!"
C cObj;
B bObj2 = cObj.f();
bObj2.foo(); // "foo?"
}