Ok, I understand the overloading thing. I've done that a few times before. I believe it's the same when you have a function that has 4 parameters, but you don't need to pass any since you determine default values...I might be wrong on that one. |
It's similar, but not quite the same thing.
Overloaded functions are multiple, unique functions that just happen to share the same name. They are only differentiated by the parameters they take.
Having default parameters is different because it calls only one singular function, but lets you omit some of the parameters in the call.
I have never done polymorphism, this is what's going to be the death of my mind it looks like. I might need to read up better to see how it works and how I can apply it to my design. |
It's the single most important aspect of OOP. The idea is you have a general base class, and derive more specific types from it.
The classic example is to have a Dog base class, from which you would derive more specific types like Poodle, or GoldenLab. The inheritance forms an "is a" relationship (ie, deriving Poodle from Dog implies that a Poodle "is a" Dog). This means that anything you can do with a Dog, you can do with a Poodle.
But the real magic of polymorphism is virtual functions. Virtual functions allow you to call general functions in the base class, which have a specific implementation in the derived class. In English, this means that you can write different code for each different class, but call them all the same way, without knowing exactly what kind of class you have.
For 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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
class Dog
{
public:
virtual void Speak() = 0; // a virtual "Speak" function
};
class Poodle : public Dog // A Poodle "is a" Dog
{
public:
virtual void Speak() { cout << "yip yip"; } // poodles are yappy dogs, so have it yip
};
class GoldenLab : public Dog // A lab "is a" Dog
{
public:
virtual void Speak() { cout << "woof woof"; } // bigger dogs have bigger barks
};
// ** THIS IS THE REAL MAGIC **
void DoSomethingWithADog( Dog* dog )
{
// notice that the dog is just a pointer to a Dog, not a Poodle or a GoldenLab
cout << "This is my dog, he is about to speak!" << endl;
dog->Speak(); // this will magically call the Speak() of whatever derived class
// the dog "actually" is. So if "dog" points to a Poodle, this will yip,
// or if it points to a lab, this will woof.
}
int main()
{
// some dogs
Poodle myPoodle;
GoldenLab myLab;
// since Poodles are Dogs, we can pass a pointer to a poodle as if it were a pointer to a dog:
DoSomethingWithADog( &myPoodle ); // works. When this function calls Speak, it will
// call the Poodle's speak.
// same with a lab:
DoSomethingWithADog( &myLab ); // this time, when it calls Speak, it will call
// GoldenLab's speak
}
|
This applies to your menu option in a bit less obvious way.
You could have a general 'MenuOption' class that has an "Action" function. You can then derive specific classes from MenuOption, each with their own Action function... and each Action function can do a different thing.
Continuing with your posts....
1 2
|
MainMenu.AddOption("MultiPlayer", [&] () {MultiMenu.Play;});
MainMenu.AddOption("Settings", std::bind(&Menu::Play, std::ref(SettingsMenu)));
|
Your Settings option here looks good. you're telling it to call
SettingsMenu.Play()
. But your MultiPlayer option is missing the function call parenthesis. You probably meant to do this:
MainMenu.AddOption("MultiPlayer", [&] () {MultiMenu.Play(); } );
Also... since your option is supposed to return an int, you probably should be returning something:
MainMenu.AddOption("MultiPlayer", [&] () {return MultiMenu.Play(); } );
------
void AddOption (std::string option = "", std::function<int ()> func)
Parameters that have a default value are optional. If you make one parameter optional,
all others that come after it must also be optional. So if you give "option" a default value here, you must also give "func" one as well.
I don't recommend it. I'd say get rid of the default params here.
C:\Programming\Menu_Example2\..\lib\menu2.h|111|error: no matching function for call to 'std::vector<std::function<int()> >::resize(std::vector<std::basic_string<char> >&)'|
This suggests you are using resize incorrectly. Can't tell what you're doing wrong because you didn't show that particular line of code.
Do I need to overload my AddOption function to handle each possibility??? I wasn't quite expecting both of them to be wrong. The std::function seems to be the easiest and definitely the most pleasant to look at. |
You only need to make AddOption overloads if you need to have multiple different types of objects that you are sending to the menu. Really, my answer to this question would be "no", because you should try to come up with a design that has a unified interface (ie: a common interface by which all menu options can be activated the same way).
Callbacks (function<void()>) are one way to do this. As is polymorphism. Personally I prefer polymorphism.
Edit: Was able to fix it by changing the defaults, but I'm not sure it was the correct way:
void AddOption (std::string option = "", std::function<int ()> func = "") {
|
That shouldn't work. You are assigning a string ("") to func. func is not a string, it's a function.
Get rid of the default parameters. They're just screwing you up. I'm willing to be that your ambiguous call errors are all because of to them.