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?"
}
Related
I would like to hide a virtual method instead of override. I know for historic / compatibility reasons the override specifier is optional and overriding happens implicitly.
To stop overriding I usually adjusted the signature by adding a defaulted "Dummy" parameter. Is there a better way?
Assume this code:
#include <iostream>
class A{
public:
virtual void Foo()
{
std::cout << "A::Foo";
}
};
class B : public A
{
public:
void Foo() /*not override, just hide*/
{
std::cout << "B::Foo";
}
};
int main()
{
B b{};
A& a = b;
a.Foo(); //should print A::Foo - but prints B::Foo
}
What I did so far is this:
#include <iostream>
class A{
public:
virtual void Foo()
{
std::cout << "A::Foo";
}
};
template<typename T>
class reintroduce{};
class B : public A
{
public:
void Foo(reintroduce<B> = {}) /*not override, just hide*/
{
std::cout << "B::Foo";
}
};
int main()
{
B b{};
A& a = b;
a.Foo(); //should print A::Foo
}
The question is not too clear on the requirements of "hiding" but the following effectively "hides" the inherited method in the derived class, while not changing its visibility/accessibility in the base class.
#include <iostream>
class A {
public:
virtual void Foo()
{ std::cout << "A::Foo"; }
};
class B : public A
{
private:
using A::Foo;
};
int main()
{
B b;
b.Foo(); // error, cannot access private member
b.A::Foo(); // ok, calls A::Foo
A& a = b;
a.Foo(); // ok, calls A::Foo
}
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
Is there a way to override separately functions with same names (from two parents) in a base class?
I am looking for something like this:
#include<iostream>
using namespace std;
class A {
public:
virtual void foo() {
cout << "A::Foo" << endl;
}
};
class B {
public:
virtual void foo() {
cout << "B::Foo" << endl;
}
};
class C : public A, public B {
public:
/*virtual void A::foo() {
cout << "C::Foo" << endl;
}*/
};
int main() {
C c;
c.A::foo(); // want to get C::Foo here
}
No you can't do this. If you want to avoid access to class A; via class C; explicit scope resolution make A private:
class C : private A, public B {
// ^^^^^^^
public:
};
If you want to prefer the implementation of A you can specify what you want to use explicitly:
class C : public A, public B {
public:
using A::foo();
};
class A;
{
private:
int a;
public:
virtual int getV() { return a; }
} a;
class C : public A;
{
private:
int c;
public:
int getV() { return c; }
} c;
class D
{
public:
A* liste;
} d;
Memory for liste may be allocated and A::a and C::c are holding values. Now if I put c in D::liste[0] and give it out with
cout << d.liste[0].getV();
it prints A::a. Why doesn't it print out C::c although I declared A::getV() as virtual?
C++ polymorphism works only for pointers and references. liste[0] has type A, not A* or A&, so the liste[0].getV() call is not dispatched virtually. It just calls A::getV().
I wrote the program like this and getting the correct result as expected
#include <iostream>
using namespace std;
class A
{
private:
int a;
public:
virtual int getV() { cout<<"A";return a; }
};
class C : public A
{
private:
int c;
public:
virtual int getV() { cout<<"C";return c; }
};
class D
{
public:
A* liste[2];
};
int main()
{
D d;
d.liste[0]=new C();
d.liste[1]=new A();
cout<<d.liste[0]->getV();
return 0;
}
Just have a look at it..
Assume the following simple case (notice the location of virtual)
class A {
virtual void func();
};
class B : public A {
void func();
};
class C : public B {
void func();
};
Would the following call call B::func() or C::func()?
B* ptr_b = new C();
ptr_b->func();
Your code is invalid C++. What are the parentheses in class definition?
It depends on the dynamic type of the object that is pointed to by pointer_to_b_type.
If I understand what you really want to ask, then 'Yes'. This calls C::func:
C c;
B* p = &c;
p->func();
Examples using pointers as well as reference.
Using pointer
B *pB = new C();
pB->func(); //calls C::func()
A *pA = new C();
pA->func(); //calls C::func()
Using reference. Note the last call: the most important call.
C c;
B & b = c;
b.func(); //calls C::func()
//IMPORTANT - using reference!
A & a = b;
a.func(); //calls C::func(), not B::func()
Online Demo : http://ideone.com/fdpU7
It calls the function in the class that you're referring to. It works it's way up if it doesn't exist, however.
Try the following code:
#include <iostream>
using namespace std;
class A {
public:
virtual void func() { cout << "Hi from A!" << endl; }
};
class B : public A {
public:
void func() { cout << "Hi from B!" << endl; }
};
class C : public B {
public:
void func() { cout << "Hi from C!" << endl; }
};
int main() {
B* b_object = new C;
b_object->func();
return 0;
}
Hope this helps