C++: Is "Virtual" inherited to all descendants - c++

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

Related

How do I determine what a function will be called if it's virtual and when it is not?

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.

Can a pointer to subclass be assigned to varibale with type of superclass?

Suppose there is a class A which has two subclasses, Aa and Ab. I want to make an array that can store pointers to objects of class Aa and Ab. If an array is declared with the type of class A, is this valid? If not, how can I accomplish this? For example:
A *arr;
//space allocated
Ab *obj1;
arr[x] = obj1;
On a related note, I want to write a function that when given a location, will return the object stored at that location in the array. If the above works and I have an array of objects of either Aa or Ab, the function could return an object of either type Aa or Ab. If the return type of the function is specified as A, the superclass, is this valid? If not, I have looked at template functions but cannot find a straight answer about just having the return type be variable, not the parameters. For this example, the function's parameter is always going to be int, but it could return an Aa or an Ab, depending on what is at that location in the array.
Yes that is the way polymorohism is achieved (using pointer to base class) and virtual methods.
Here is an example:
#include <iostream>
using namespace std;
#include <vector>
class A{
public:
virtual void foo()const{
std::cout << "A::foo()" << std::endl;
}
};
class Aa : public A {
public:
virtual void foo()const{
std::cout << "Aa::foo()" << std::endl;
}
};
class Ab : public A {
public:
virtual void foo()const{
std::cout << "Ab::foo()" << std::endl;
}
};
int main(){
A* ptrA[3];
A* a = new A;
Aa* aa = new Aa;
Ab* ab = new Ab;
ptrA[0] = aa;
ptrA[1] = ab;
ptrA[2] = a;
for(int i(0); i != 3; ++i)
ptrA[i]->foo();
delete a;
delete aa;
delete ab;
return 0;
}
Remember that C++ is Invariant not Contravariant which means you cannot assign a derived object a base object:
A* a = new A;
Ab* ab = a; // error
Is valid to have an array of base pointers, also you can use dynamic_cast to know in run time the return type of your array and use the API from the derived class. See and example below.
struct Base { virtual void do_something() {} };
struct Derived1 : Base
{
void first() const { std::cout << "first" << std::endl; }
void do_something() override {}
};
struct Derived2 : Base
{
void second() const { std::cout << "second" << std::endl; }
void do_something() override {}
};
Base& get(int option)
{
static std::vector<Base*> b {new Derived1{}, new Derived2{}};
return !option ? *b[0] : *b[1];
}
int main()
{
const int option {0};
// const int option {1};
if (Derived1* derived {dynamic_cast<Derived1*>(&get(option))})
{
derived->first();
}
else if (Derived2* derived {dynamic_cast<Derived2*>(&get(option))})
{
derived->second();
}
}

How to call derived class method from base class pointer?

I have a class structure similar to the following
class A
{
public:
A(void);
~A(void);
void DoSomething(int i)
{
std::cout << "Hello A" << i << std::endl;
}
};
class B : public A
{
public:
B(void);
~B(void);
void DoSomething(int i)
{
std::cout << "Hello B" << i << std::endl;
}
};
class Ad : public A
{
public:
Ad(void);
~Ad(void);
};
class Bd : public B
{
public:
Bd(void);
~Bd(void);
};
I want to store instances of the derived classes in a container (standard map) as a collection of A*, then iterate through the container and call methods for each instance.
#include "A.h"
#include "B.h"
#include "Ad.h"
#include "Bd.h"
#include <map>
int main(int argc, char** argv)
{
std::map<int,A*> objectmap;
objectmap[1] = new Ad();
objectmap[2] = new Bd();
for (std::map<int,A*>::iterator itrobject = objectmap.begin();
itrobject!=objectmap.end(); itrobject++)
{
itrobject->second->DoSomething(1);
}
return 0;
}
The above code produces the following output.
Hello A1
Hello A1
Where I was expecting
Hello A1
Hello B1
because I was expecting DoSomething in B to hide DoSomething in A, and because I am storing A pointers, I would expect no object slicing (and looking at the object pointer in the debugger shows that the object has not been sliced).
I have tried down casting and dynamic casting the pointer to B, but it slices away the data members of Bd.
Is there any way to call B::DoSomething without casting the pointer to Bd? And if not, if I have many derived classes of B (e.g. Bda, Bdb, Bdc etc), is there some way to use RTTI to know which derived class to cast it to?
You need to make DoSomething() a virtual function in both classes to get the polymorphic behavior you're after:
virtual void DoSomething(int i) { ...
You don't need to implement virtual functions in every sub class, as shown in the following example:
#include <iostream>
class A {
public:
virtual void print_me(void) {
std::cout << "I'm A" << std::endl;
}
virtual ~A() {}
};
class B : public A {
public:
virtual void print_me(void) {
std::cout << "I'm B" << std::endl;
}
};
class C : public A {
};
int main() {
A a;
B b;
C c;
A* p = &a;
p->print_me();
p = &b;
p->print_me();
p = &c;
p->print_me();
return 0;
}
Output:
I'm A
I'm B
I'm A

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?"
}

Calling upper level class member C++

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.