So suppose I have:
Class A
{
void A::DoSomething();
A::A()
};
Class B : public A
{
void B::DoSomething();
B::B()
}
Class C : public A
{
void C::DoSomething();
C::C()
}
B obj1;
C obj2;
void RemoveObjectFromListOrSomethingSimiliar(A objToLookFor)
{
//assuming you found the object, how would you call the top-level DoSomething() (for example B::DoSomething() ) instead of the A::DoSomething()?
}
I'm not sure if that makes sense
[EDIT]
Ok, so that's kinda working. Though it's still redirecting to the base method, which confuses me.
B obj1;
c obj2;
AList.push_back(obj1);
AList.push_back(obj2);
//later, in another method:
A objInBack = AList.back();
objInBack.DoSomething();
AList.pop_back();
The objInBack refers to the A-level of the class structure and subsequently calls that level of DoSomething(). I've changed A's methods to virtual, so is there some way to explicitly define the level of execution or?
I'm not sure I got your question right, but I guess what you need is dynamic binding.
Here is an example based on your pseudocode.
#include <iostream>
class A
{
public:
A() {}
virtual void DoSomething() { std::cout << "A did something!" << std::endl; }
};
class B : public A
{
public:
B() {}
void DoSomething() { std::cout << "B did something!" << std::endl; }
};
class C : public A
{
public:
C() {}
void DoSomething() { std::cout << "C did something!" << std::endl; }
};
void DoSomethingWithSomething(A* ptr)
{
ptr->DoSomething();
}
int main()
{
A* obj1 = new A();
A* obj2 = new B();
A* obj3 = new C();
B* obj4 = new B();
C* obj5 = new C();
DoSomethingWithSomething(obj1);
DoSomethingWithSomething(obj2);
DoSomethingWithSomething(obj3);
DoSomethingWithSomething(obj4);
DoSomethingWithSomething(obj5);
}
The output would then be:
A did something!
B did something!
C did something!
B did something!
C did something!
I would declare DoSomething virtual, and call it just as objToLookFor.DoSomething().
By the way, your RemoveObjectFromListOrSomethingSimiliar perhaps needs to accept A* as parameter, not just A.
Related
Look at this excerpt of a program.
I see that cout << obj->foo(); call is not polymorphic. Actually, it is obvious, because it has no virtual specificator.
But I am confused with cout << ((B*)obj)->foo(); Why the program does not use the B's definition of virtual function and will call the third version of foo()?
#include <iostream>
using namespace std;
class A{
public:
int foo(){ return 1; }
};
class B: public A{
public:
virtual int foo(){ return 2; }
};
class C: public B{
public:
int foo(){ return 3; }
};
int main() {
A* obj = new C;
cout << obj->foo();
cout << ((B*)obj)->foo();
cout << ((C*)obj)->foo();
return 0;
}
A::foo() is not virtual. Calling foo() via an A* pointer (or A& reference) will call A::foo() directly without any polymorphic dispatch.
B::foo() is virtual. Calling foo() via a B* pointer (or B& reference) will dispatch the call to the most derived implementation of foo() that exists in the object that the B* (or B&) refers to.
C derives from B, and C::foo() overrides B::foo(), and obj points to a C object, which is why C::foo() gets called by polymorphic dispatch when foo() is called via a B* or C* pointer (or a B& or C& reference).
Because ((B*)obj)->foo(); behaves by design like B* b = (B*)obj; b->foo() and calls C::foo. You may call the base's method explicitly like ((B*)obj)->B::foo();.
#include <iostream>
using namespace std;
class A{
public:
int foo(){ return 1; }
};
class B: public A{
public:
virtual int foo(){ return 2; }
};
class C: public B{
public:
int foo() override { return 3; }
};
int main() {
A* obj = new C;
cout << obj->foo();
cout << ((B*)obj)->B::foo();
cout << ((C*)obj)->foo();
return 0;
}
Output: 123
Member function foo is virtual from class B downwards, i.e. also in C, even if it is not marked virtual or override there.
Thus, call ((B*)obj)->foo() is a virtual call, actually resulting in calling C::foo.
#include <iostream>
class A {
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() { return foo; }
};
class C {
private:
A baz;
public:
C(A faz) { baz = faz; }
A get() { return baz; }
};
int main(void) {
C boo(B(1));
std::cout << boo.get().method() << std::endl;
return 0;
}
I have a base class A which B is a derived class of. Class C takes an A yet I have passed a derived class (B) in its place. No warnings or errors passing a B to C, but I'd like to have method visibility of method() in the above situation.
I'm not very familiar with virtual but I did try to add virtual int method() = 0; to A which lead to further errors.
Consider were I to add a second derived class:
class D : public A {
public:
D(int bar) { foo = bar; }
int method() { return foo+1; }
};
I'd like C to be able to take either B or D and my best assumption would be to take an A and let it handle it.
How do I use polymorphism correctly in this fashion?
Expected output with the below:
int main(void) {
C boo(B(1));
C boz(D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Would be:
1
3
First of all, in order to use A polymorphically, you need to add a virtual destructor, otherwise you will run into undefined behavior when trying to destroy the object. Then the method that you want to call through A must be virtual as well. If it shouldn't have an implementation in the base class itself, make it pure virtual:
class A {
protected:
int foo;
public:
virtual ~A() {}
virtual int method() = 0;
};
Then in C you need to use pointers or references to A, since polymorphism only works with those.
If you want C to own the A, as your code example to suggest, then you need to provide a destructor deleting the pointer and you need to disable copying of the class (or decide on some useful semantics for it):
class C {
private:
C(const C&); // Don't allow copying
C& operator=(const C&); // Don't allow copying
A* baz;
public:
C(A* faz) : baz(faz) { }
~C() { delete baz; }
A& get() { return *baz; }
};
int main(void) {
C boo(new B(1));
C boz(new D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Ideally you would upgrade to C++11 and use std::unique_ptr<A> instead of A* as member. But even if you can't do that, consider using boost::scoped_ptr<A>, which will manage the deletion for you (you don't need the destructor) and will make the class non-copyable by default. It also provides better exception-safety to encapsulate allocations in smart pointers like that.
If you need to call method() of type B using base class type A there has to be lookup during the runtime. The lookup is necessary to answer the question: Which method should be called? - the one that corresponds the type in a current line? Or other method in inheritance hierarchy?" If you expect method() from class B to be called when you have pointer or reference to A then you have to create a lookup table. This table is called vtable (from virtual functions table) and it's defined by adding virtual keyword to functions.
#include <iostream>
class A {
public:
virtual ~A(){}
virtual int method() = 0;
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() {
std::cout << "Calling method() from B" << std::endl;
return foo; }
};
class C {
private:
A* baz;
public:
C(A* faz) { baz = faz; }
A* get() { return baz; }
};
int main(void) {
A* element = new B(1);
C boo(element);
boo.get()->method();
return 0;
}
It prints "Calling method() from B". Please keep in mind that the code is for presentation purposes and it's not good from best practices perspective.
In the following code, the function foo is copy constructing a Base object c from a Derived object d. My question is: are we getting an exact copy? Because I'm not getting the polymorphic behavior I'm expecting
#include<iostream>
class Base
{
public:
virtual void sayHello()
{
std::cout << "Hello Base" << std::endl ;
}
};
class Derived: public Base
{
public:
void sayHello() override
{
std::cout << "Hello Derived" << std::endl ;
}
};
void foo(Base* d)
{
Base* c = new Base(*d);
c->sayHello() ;
}
int main()
{
Derived d;
foo(&d) ; //outputs Hello Base
}
There is no virtual constructor nor copy constructor.
However, it is possible to define a function that behaves like one.
In my case, it is the virtual member function copy() which I added to OP's sample:
#include <iostream>
class Base
{
public:
virtual Base* copy() const { return new Base(*this); }
virtual void sayHello()
{
std::cout << "Hello Base" << std::endl ;
}
};
class Derived: public Base
{
public:
virtual Base* copy() const override { return new Derived(*this); }
void sayHello() override
{
std::cout << "Hello Derived" << std::endl ;
}
};
void foo(Base* d)
{
Base* c = d->copy();
c->sayHello() ;
}
int main()
{
Derived d;
foo(&d) ; //outputs Hello Derived
return 0;
}
Output:
Hello Derived
Live Demo on coliru
The drawback is that every derived class of Base has to provide it to make it function properly. (I've no idea how to convince the compiler to check this for me with any trick.)
A partial solution could be to make copy() pure virtual in the class Base (assuming it is not meant to be instantiable).
you may wonna change the line of new
Base* c = new Derived(*d);
so you have the type Derived in a Base pointer. During runtime it is looked up, which type it is and you get the right output.
let me know if im wrong... just created this out of my mind on the fly.
To answer your question about whether or not this is copy constructing lets add some members. Base will have a member, m_b and Derived will inherit m_b but also have another member m_d
#include <iostream>
struct Base {
const int m_b;
Base() = delete;
Base(const int a_b) : m_b(a_b) {}
virtual void sayHello() {
std::cout << "Base " << m_b << std::endl;
}
};
struct Derived : public Base {
const int m_d;
Derived() = delete;
Derived(const int a_b, const int a_d) : Base(a_b), m_d(a_d) {}
void sayHello() override {
std::cout << "Derived " << m_b << ' ' << m_d << std::endl;
}
};
void foo(Derived* a) {
Base* b = new Base(*a);
b->sayHello(); // Output is "Base 1", 1 was copied from argument a
}
void bar(Derived* a) {
Base* d = new Derived(*a);
d->sayHello(); // Output is "Derived 1 2"
}
int main() {
Derived d(1, 2);
foo(&d);
bar(&d);
return 0;
}
The line:
Base* b = new Base(*a);
Created a Base and so sayHello calls Base's implementation which doesn't know about m_d. However this line does copy m_b from the derived class
The line:
Base* d = new Derived(*a);
Created a Derived and so sayHello calls Derived's implementation which copied both m_b and m_d
Expected polymorphic behavior will come into existence when the Base class pointer points to Derived class object. Then at run time the actual type of object pointed to by the Base class pointer will be checked and appropriate function will get called.
Base* c = new Base(*d); // <<-- case of object slicing
Here, c points to Base class object. Therefore, c->sayHello() ; is bound to call the Base::sayHello() at runtime.
are we getting an exact copy?. No since you are creating a Base object due to new Base. Due to object slicing the Base part of the *d object is passed to copy c'tor and what you get is corresponding Base object.
Base *c = new Derived(*d); will give the expected behavior.
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
I know this question must have been covered endless of times, but I've searched the previous questions, and nothing seems to pop.
It's about inheritance and virtual functions i C++. I have a problem with calling virtual functions in subclasses from the superclass.
Let me give an example. Start of with three classes, which inherit from each other.
class A {
void foo() { bar() }
virtual void bar() { }
};
class B : public A {
virtual void bar() { }
};
class C : public B {
virtual void bar() { // do something }
};
Now I wanna have a variable declared as B* but instantiated as C*.
B* myObject = new C();
myObject->foo();
When I do this, and call foo() on myObject, then A::foo() is calling bar(). But only B::bar() is called, not C::Bar() - which in reality myObject is, even though it's declared as B, which again affects that "// do nothing" doesn't get executed.
How do I tell A::foo(), that it needs to look at lowest implementation?
Makes sense?
// Trenskow
EDIT:
C::Foo is not the problem. Foo is being called in class A, as it's the only place it's implemented. The problem arises, when A:Foo calls Bar(). Then B:Bar is called and not C::Bar.
Maybe the problem is, that in my implementation, I only get a void* pointer to the object in A.
Like this:
void A:Foo(void *a) {
A* tmpA = static_cast<A*> (a);
tmpA->bar();
}
Now the compiler thinks, that tmpA is an A. But somehow it manages to figure that it's a B*, and calls B::Bar, when in fact tmpA is a C* and it should be calling C::Bar.
The following prints "A::foo C::bar" as expected. Are you getting something different? B::bar is never called because C is the actual runtime type of the object. In C::bar, you could call B::bar explicitly by adding B::bar(); to its body.
#include <iostream>
using namespace std;
class A {
public:
void foo() { cout << "A::foo "; bar(); }
virtual void bar() { }
};
class B : public A {
public:
virtual void bar() { cout << "B::bar" << endl; }
};
class C : public B {
public:
virtual void bar() { cout << "C::bar" << endl; }
};
int main()
{
B* c = new C();
c->foo();
return 0;
}
void A:Foo(void *a) {
A* tmpA = static_cast<A*> (a);
tmpA->bar();
}
This is undefined behaviour. You cannot cast a B* to a void*, then cast that void* back to an A*. If you want it to work properly, you have to ditch the void*. Alternatively, you could try dynamic_cast.
Assuming you mistyped your last block of code and the names match:
B* variable = new C();
variable->foo();
Then the C::Foo method is being called or you are using a terribly bad compiler.
(This also assumes that you don't actually have a compiler error in C::Foo, and that the comment is actually something like std::cout << "Hi mom!" << std::endl;)
Don't you mean:
B* myObject = new C();
myObject->foo(); // not variable->foo()
class A
{
public:
void foo() { bar(); }
virtual void bar() { std::cout << "A"; };
};
class B : public A
{
public:
virtual void bar() { std::cout << "B";};
};
class C : public B
{
public:
virtual void bar() { std::cout << "C"; }
};
This prints 'C' as expected.
I don't follow. You're saying
But only B::bar() is called, not
C::Bar()
No. You invoked the constructor of class C, which means that the vtable makes bar() point to C::bar(), so calling foo() in this case would go straight to C::bar().
If you want to force A::foo() to explicitly only call A's implementation, you can do that by just writing
void foo() { A::bar(); }
What exactly are you trying to do?
what compiler are you using? Visual Studio (IIRC) usually has the runtime type information turned off by default so maybe its just something simple as that?