Virtual functions: how to call the proper function?

Dec 15, 2017 at 11:50pm
Let's say I've defined in my interface,

1
2
3
4
5
//interface
class iClass {
     public:
     virtual void display(std::ostream&) const = 0;
};


And I have a class that derived from it,

1
2
3
4
5
//abstract class
class Class : public iClass {
	public:
		void display(std::ostream&) const;
	};


And I have two other classes deriving from Class

1
2
3
4
5
6
7
8
9
10
11
//concrete class
ClassA : Class {
     public:
     void display(std::ostream&) const;
};

//concrete class
ClassB : Class {
     public:
     void display(std::ostream&) const;
};


Say my main is,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void display(const char* aPointer, iClass* const arr[], int n) {
     //some stuff
     arr[i]->display(cout);
}

int main () {
	// Create Accounts for Angelina
	iClass* Angelina[2];
    
	// initialize Angelina's Accounts
	Angelina[0] = CreateAccount("Savings", 400.0); 
	Angelina[1] = CreateAccount("Chequing", 400.0);
	display("Angelina", Angelina, 2);
                           .  .  .
}


I also have an allocator,

1
2
3
4
5
6
7
8
9
10
	iClass* CreateAccount(const char* type, double amount) {
		iClass* a = nullptr;
		if ('S' == toupper(type[0])) {
			a = new ClassA(amount);
		}
		else if ('C' == toupper(type[0])) {
			a = new ClassB(amount);
		}
		return a;
	}


In my main, how do I call the appropriate display function? My program keeps executing the void Class::display(std::ostream&) function from my abstract class 'Class', but I want it to call the corresponding void display(std::ostream&) function from whichever class that the object was created.
So, if a = new ClassB(amount); was executed, I want it to run void ClassB::display(std::ostream&)

As it is now, no matter what I do, no matter what type of object was created (ClassA or ClassB), it always calls the display function from Class
Last edited on Dec 15, 2017 at 11:57pm
Dec 16, 2017 at 1:16am
If you want dynamic dispatch, you must use the virtual keyword:

1
2
3
4
class Class : public iClass {
	public:
		virtual void display(std::ostream&) const;
};


Here's a complete example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# include <iostream>

struct IBase {
    virtual std::ostream& display(std::ostream&) const = 0;
};

struct Base: IBase {
    virtual std::ostream& display(std::ostream& s) const override
    { return s << "Class::display()\n"; }
};
	
struct A: Base {
    std::ostream& display(std::ostream& s) const override
    { return s << "ClassA::display()\n"; }
};
struct B: Base {
    std::ostream& display(std::ostream& s) const override 
    { return s << "ClassB::display()\n"; };
};

int main() { 
    A my_a;
    B my_b;
    IBase &a = my_a, &b = my_b;
    a.display(std::cout); b.display(std::cout);
}


Live demo:
http://coliru.stacked-crooked.com/a/45b08066b09fe7e1
Last edited on Dec 16, 2017 at 1:27am
Dec 16, 2017 at 5:38pm
Always missing something so elementary, thank you.

I was under the impression that virtual keyword of a function should only be in the interface class; putting it elsewhere would be for only documentation purposes. Guess not.

Thanks again!
Topic archived. No new replies allowed.