I have a particular scenario below. The code below should print 'say()' function of B and C class and print 'B says..' and 'C says...' but it doesn't .Any ideas..
I am learning polymorphism so also have commented few questions related to it on the lines of code below.
class A
{
public:
// A() {}
virtual void say() { std::cout << "Said IT ! " << std::endl; }
virtual ~A(); //why virtual destructor ?
};
void methodCall() // does it matters if the inherited class from A is in this method
{
class B : public A{
public:
// virtual ~B(); //significance of virtual destructor in 'child' class
virtual void say () { // does the overrided method also has to be have the keyword 'virtual'
cout << "B Sayssss.... " << endl;
}
};
class C : public A {
public:
//virtual ~C();
virtual void say () { cout << "C Says " << endl; }
};
list<A> listOfAs;
list<A>::iterator it;
# 1st scenario
B bObj;
C cObj;
A *aB = &bObj;
A *aC = &cObj;
# 2nd scenario
// A aA;
// B *Ba = &aA;
// C *Ca = &aA; // I am declaring the objects as in 1st scenario but how about 2nd scenario, is this suppose to work too?
listOfAs.insert(it,*aB);
listOfAs.insert(it,*aC);
for (it=listOfAs.begin(); it!=listOfAs.end(); it++)
{
cout << *it.say() << endl;
}
}
int main()
{
methodCall();
return 0;
}
Your problem is called slicing and you should check this question: Learning C++: polymorphism and slicing
You should declare this list as a list of pointers to As:
list<A*> listOfAs;
and then insert these aB and aC pointers to it instead of creating copies of objects they are pointing to. The way you insert elements into list is wrong, you should rather use push_back function for inserting:
B bObj;
C cObj;
A *aB = &bObj;
A *aC = &cObj;
listOfAs.push_back(aB);
listOfAs.push_back(aC);
Then your loop could look like this:
list<A*>::iterator it;
for (it = listOfAs.begin(); it != listOfAs.end(); it++)
{
(*it)->say();
}
Output:
B Sayssss....
C Says
Hope this helps.
Polymorphism of virtual class hierarchies only works through references or pointers to a base subobject:
struct Der : Base { /* ... */ };
Der x;
Base & a = x;
a.foo(); // calls Der::foo() from x
The function foo is dispatched polymorphically if it is a virtual function in Base; the polymorphism refers to the fact that while you are calling a member function of an object of type Base, the function that actually gets called may be implemented in the class Der.
Containers can only store elements of a fixed type. In order to store a polymorphic collection, you could instead have a container of pointers to the base class. Since you need to store the actual objects elsewhere, lifetime management is non-trivial and best left to a dedicated wrapper such as unique_ptr:
#include <list>
#include <memory>
int main()
{
std::list<std::unique_ptr<Base>> mylist;
mylist.emplace_back(new Der1);
mylist.emplace_back(new Der2);
// ...
for (p : mylist) { p->foo(); /* dispatched dynamically */ }
}
list::iterator it;
B bObj;
C cObj;
A *aB = &bObj;
A *aC = &cObj;
listOfAs.insert(it,*aB);
Do you not need to initialize "it" ?
I believe you should do it = listOfAs.begin(); before starting to insert.
Related
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();
}
}
I'm reading Scott Meyers' More Effective C++ now. Edifying! Item 2 mentions that dynamic_cast can be used not only for downcasts but also for sibling casts. Could please anyone provide a (reasonably) non-contrived example of its usage for siblings? This silly test prints 0 as it should, but I can't imagine any application for such conversions.
#include <iostream>
using namespace std;
class B {
public:
virtual ~B() {}
};
class D1 : public B {};
class D2 : public B {};
int main() {
B* pb = new D1;
D2* pd2 = dynamic_cast<D2*>(pb);
cout << pd2 << endl;
}
The scenario you suggested doesn't match sidecast exactly, which is usually used for the casting between pointers/references of two classes, and the pointers/references are referring to an object of class which both derives from the two classes. Here's an example for it:
struct Readable {
virtual void read() = 0;
};
struct Writable {
virtual void write() = 0;
};
struct MyClass : Readable, Writable {
void read() { std::cout << "read"; }
void write() { std::cout << "write"; }
};
int main()
{
MyClass m;
Readable* pr = &m;
// sidecast to Writable* through Readable*, which points to an object of MyClass in fact
Writable* pw = dynamic_cast<Writable*>(pr);
if (pw) {
pw->write(); // safe to call
}
}
LIVE
It is called cross-cast, and it is used when a class inherits from two different classes (not the other way around, as shown in your question).
For example, given the following class-hierarchy:
A B
\ /
C
If you have an A pointer to a C object, then you can get a B pointer to that C object:
A* ap = new C;
B* bp = dynamic_cast<B*>(ap);
If I declare a base class (or interface class) and specify a default value for one or more of its parameters, do the derived classes have to specify the same defaults and if not, which defaults will manifest in the derived classes?
Addendum: I'm also interested in how this may be handled across different compilers and any input on "recommended" practice in this scenario.
Virtuals may have defaults. The defaults in the base class are not inherited by derived classes.
Which default is used -- ie, the base class' or a derived class' -- is determined by the static type used to make the call to the function. If you call through a base class object, pointer or reference, the default denoted in the base class is used. Conversely, if you call through a derived class object, pointer or reference the defaults denoted in the derived class are used. There is an example below the Standard quotation that demonstrates this.
Some compilers may do something different, but this is what the C++03 and C++11 Standards say:
8.3.6.10:
A virtual function call (10.3) uses
the default arguments in the
declaration of the virtual function
determined
by the static type of the pointer or reference denoting the object. An
overriding function in a derived
class does not acquire default arguments from the function it
overrides. Example:
struct A {
virtual void f(int a = 7);
};
struct B : public A {
void f(int a);
};
void m()
{
B* pb = new B;
A* pa = pb;
pa->f(); //OK, calls pa->B::f(7)
pb->f(); //error: wrong number of arguments for B::f()
}
Here is a sample program to demonstrate what defaults are picked up. I'm using structs here rather than classes simply for brevity -- class and struct are exactly the same in almost every way except default visibility.
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
using std::stringstream;
using std::string;
using std::cout;
using std::endl;
struct Base { virtual string Speak(int n = 42); };
struct Der : public Base { string Speak(int n = 84); };
string Base::Speak(int n)
{
stringstream ss;
ss << "Base " << n;
return ss.str();
}
string Der::Speak(int n)
{
stringstream ss;
ss << "Der " << n;
return ss.str();
}
int main()
{
Base b1;
Der d1;
Base *pb1 = &b1, *pb2 = &d1;
Der *pd1 = &d1;
cout << pb1->Speak() << "\n" // Base 42
<< pb2->Speak() << "\n" // Der 42
<< pd1->Speak() << "\n" // Der 84
<< endl;
}
The output of this program (on MSVC10 and GCC 4.4) is:
Base 42
Der 42
Der 84
This was the topic of one of Herb Sutter's early Guru of the Week posts.
The first thing he says on the subject is DON'T DO THAT.
In more detail, yes, you can specify different default parameters. They won't work the same way as the virtual functions. A virtual function is called on the dynamic type of the object, while the default parameter values are based on the static type.
Given
class A {
virtual void foo(int i = 1) { cout << "A::foo" << i << endl; }
};
class B: public A {
virtual void foo(int i = 2) { cout << "B::foo" << i << endl; }
};
void test() {
A a;
B b;
A* ap = &b;
a.foo();
b.foo();
ap->foo();
}
you should get
A::foo1
B::foo2
B::foo1
This is a bad idea, because the default arguments you get will depend on the static type of the object, whereas the virtual function dispatched to will depend on the dynamic type.
That is to say, when you call a function with default arguments, the default arguments are substituted at compile time, regardless of whether the function is virtual or not.
#cppcoder offered the following example in his [closed] question:
struct A {
virtual void display(int i = 5) { std::cout << "Base::" << i << "\n"; }
};
struct B : public A {
virtual void display(int i = 9) override { std::cout << "Derived::" << i << "\n"; }
};
int main()
{
A * a = new B();
a->display();
A* aa = new A();
aa->display();
B* bb = new B();
bb->display();
}
Which produces the following output:
Derived::5
Base::5
Derived::9
With the aid of the explanation above, it is easy to see why. At compile time, the compiler substitutes the default arguments from the member functions of the static types of the pointers, making the main function equivalent to the following:
A * a = new B();
a->display(5);
A* aa = new A();
aa->display(5);
B* bb = new B();
bb->display(9);
As other answers have detailed, its bad idea. However since no one mentions simple and effective solution, here it is: Convert your parameters to struct and then you can have default values to struct members!
So instead of,
//bad idea
virtual method1(int x = 0, int y = 0, int z = 0)
do this,
//good idea
struct Param1 {
int x = 0, y = 0, z = 0;
};
virtual method1(const Param1& p)
As you can see from the other answers this is a complicated subject. Instead of trying to do this or understand what it does (if you have to ask now, the maintainer will have to ask or look it up a year from now).
Instead, create a public non-virtual function in the base class with default parameters. Then it calls a private or protected virtual function that has no default parameters and is overridden in child classes as needed. Then you don't have to worry about the particulars of how it would work and the code is very obvious.
This is one that you can probably figure out reasonably well by testing (i.e., it's a sufficiently mainstream part of the language that most compilers almost certainly get it right and unless you see differences between compilers, their output can be considered pretty well authoritative).
#include <iostream>
struct base {
virtual void x(int a=0) { std::cout << a; }
virtual ~base() {}
};
struct derived1 : base {
void x(int a) { std:: cout << a; }
};
struct derived2 : base {
void x(int a = 1) { std::cout << a; }
};
int main() {
base *b[3];
b[0] = new base;
b[1] = new derived1;
b[2] = new derived2;
for (int i=0; i<3; i++) {
b[i]->x();
delete b[i];
}
derived1 d;
// d.x(); // won't compile.
derived2 d2;
d2.x();
return 0;
}
With the following code, I would expect output to be B.f B.f DD.f, but instead the output I get is B.f B.f B.f. How is that possible, when DD derives from D which has f as virtual.
class B
{
public:
void f() { cout << "B.f "; }
};
class D : public B
{
public:
virtual void f() { cout << "D.f "; }
};
class DD : public D{
public:
virtual void f() { cout << "DD.f "; }
};
B * b = new B();
B * d = new D();
B * dd = new DD();
b->f();
d->f();
dd->f();
Functions become virtual from the level they were declared virtual up. You first declare f virtual in D, which means the dynamic dispatch will only happen from D upwards. B doesn't, nor should it know about the deriving classes.
Think about how the compiler sees it:
You have a pointer to B - B has the following definition:
class B
{
public:
void f() { cout << "B.f "; }
};
Since f is not virtual, I'll just go ahead and resolve the call statically - i.e. B::f().
For dynamic dispatch to work from a pointer to B, you need to make f() virtual in B:
class B
{
public:
virtual void f() { cout << "B.f "; }
};
You need to set B::f() to virtual, without set B::f() to virtual, it won't appear in B virtual table(vtbl), thus B::f() is called instead of dispatch the call to derived class.
class B
{
public:
virtual void f() { cout << "B.f "; }
};
As soon as you declare f() virtual in B,this starts to maintain a virtual table that holds the function pointers of all the other functions of same name of derived classes. This is a lookup table that is used to resolve function calls in a dynamic/late binding manner.
When you use a reference or a pointer to call a method, the compiler searches in the type of the pointer or reference at the declaration of the method (here it searches in B the declaration of some method with signature f()). When it finds one :
if it is NOT marked as virtual, then it solves it as a call to the method defined for this class - this is a static binding.
if it is marked as virtual, then the method called will be the appropriate one of the object referenced or pointed by - this is a dynamic binding.
The next test would have been :
DD * dd = new DD();
D * d = dd;
B * b = d;
b->f();
d->f();
dd->f();
One single object new DD() that is used/viewed differently... Each type can be thought as a kind of view you have on an object. If you see it as a B then f() does something but always the same thing, but if you see it as D or DD, f() does something different...
If you meet someone in the street, the standard way for him to salute you is to say hello, but for the same person, when he meets a friend of him he can either say hi! or Yo! :
class Person {
public:
void salute() { cout << "Hello" << endl; }
};
class Friend : public Person {
public:
virtual void salute() { cout << "Hi!" << endl; }
};
class RoomMate : public Friend {
public:
virtual void salute() { cout << "Yo!" << endl; }
};
void asACustomer(Person &p) {
p.salute(); // static binding, we need the standard politeness
}
void asAFriend(Friend &f) {
p.salute(); // dynamic binding, we want an appropriate message...
}
RoomMate joe;
asCustomer(joe);
asFriend(joe);
With static binding you know at compile time which method is called; with dynamic binding you cannot, you only know that an appropriate one will be. This is a key point in sub-typing polymorphism.
In general, be careful when mixing static and dynamic binding for a method.
Okay, I'm writing a game that has a vector of a pairent class (enemy) that s going to be filled with children classes (goomba, koopa, boss1) and I need to make it so when I call update it calls the childclasses respective update. I have managed to create a example of my problem.
#include <stdio.h>
class A{
public:
virtual void print(){printf("Hello from A");}
};
class B : public A{
public:
void print(){printf("Hello from B");}
};
int main(){
A ab = B();
ab.print();
while(true){}
}
Output wanted: "Hello from B"
Output got: "Hello from A"
How do I get it to call B's print function?
Polymorphism only works on pointers and references. If you assign a B to an A, it becomes an A and you lose all B-specific information, including method overrides. This is called "slicing"; the B parts are "sliced" off the object when it is assigned to an object of a parent class.
On the other hand, if you assign a B* to an A*, it looks like an A*, but is still really pointing to a B, and so the B-specific information remains, and B's virtual overrides will be used.
Try:
int main(){
A* ab = new B();
ab->print();
delete ab;
while(true){}
}
The same also applies to assigning a B to an A& (reference-to-A), e.g.
int main(){
B b;
A& ab = b;
ab.print();
while(true){}
}
Your virtual keyword is correctly placed, you need to use pointers or references though.
You need to call the parent's update method before any processing by the descendant classes:
struct Base_Class
{
virtual void update(void)
{
cout << "Updating Base_Class.\n";
}
};
struct Goomba : public Base_Class
{
void update(void)
{
// Invoke the parent method first.
Base_Class::update();
// Perform Descendant operations
cout << "Updating Goomba\n";
}
};
Here is the implementation:
#include <iostream>
using std::cout;
void Update_Player(Base_Class& b)
{
b.update();
return;
}
int main(void)
{
Goomba g;
g.update();
Goomba g2;
std::vector<Base_Class *> container;
container.push_back(&g);
container.push_back(&g2);
std::vector<Goomba>::iterator iter;
for (iter = container.begin();
iter != container.end();
++iter)
{
Update_Player(*(*iter));
}
return 0;
}