I am new to C++ and trying to learn the code for Extreme Tux Racer. In the code in the main method it says manager.Run(...). To me this looks like it is running the Run method of a manager object in the State namespace.
switch (g_game.argument) {
case 0:
State::manager.Run(SplashScreen);
break;
case 4:
g_game.toolmode = TUXSHAPE;
State::manager.Run(Tools);
break;
case 9:
State::manager.Run(OglTest);
break;
}
I assume that the manager object's run method has to be declared and defined somewhere. But I searched all of the included files for the word manager and could not find it. What am I missing here?
It looks like they set file name the same as class name, which is a good way to do. So in states.h, you could see all definition:
class State {
//...
static Manager manager; // manager is static member
//...
};
static member could be accessed by :: , . or -> operator.
State::manager.Run(..); // valid
State state;
state.manager.Run(..); // valid as well
State *pState = &state;
pState->manager.Run(..); // also valid
Related
Functions under difference name spaces are needed, the name space reflects different data version, but the all the functions has the same signature. Please see example
For version v_1_0 this function is needed v_1_0::decoder::decoding( ... )
For version v_1_1 then this shall be called v_1_1::decoder::decoding( ... )
I receives the version string from somewhere else. The version format is exactly as the namespace, I wonder if I could generated the function call from the namespace string variable.
The reason I'm asking for this question is, there are so many versions already and will be more added soon. I have to create a long if else or switch loop to call the function which is very annoying
switch (version) {
case v_1_0:
v_1_0::decoder::decoding( ... )
break;
case v_1_1:
v_1_1::decoder::decoding( ... )
break;
....
default:
break;
}
Would be nice to have something like
auto name_space = get_namespace( version );
name_space::decoding( ... )
This cannot be done. Namespace names are discarded when you compile the program.
You also cannot have a variable of type namespace. If each version was a class, or an instance of a class, you could create a function that returns the appropriate instance - but that is not the case for namespaces.
I have a class, DBProc, which makes a connection to PostgreSQL, and allows user to submit queries/retrieve results.
Functionally, everything works.
The DBProc::connect() function takes an optional argument for connection type. The 3 variants are: direct, lazy, asynchronous.
I have code that instantiates the correct connection class according to user's choice. I initialize 3 unique_ptr<> beforehand, one for each possible connection class, then use an switch statement to choose the selected class type.
This all works fine...but
My preference would be to have ONE class var that holds a reference to
the connection class
(all the classes have the exact same functionality), but I see no easy way to do this.
'auto& currentConnection = lazyConnection' works fine in the switch statement, but of course goes out of scope after the code block.
If there was a way to create a var within a block and allow it to be seen outside the block, without 1st declaring it, that would work, but I don't believe that's possible in c++.
I can't declare it first because all these classes require initialization upon declaration.
So...c++atch 22 ;-)
So, every time I need to use the connection, I need a switch statement to select the right pointer.
I've looked at templates, unions, extern, and don't see a way to do it with any of these.
If anyone knows if there is a way to do this, please describe.
Here's a code snippet of class func:
bool DBProc::connect(ConnectionType type) {
...
unique_ptr<pqxx::connection> connect;
unique_ptr<pqxx::lazyconnection> lzy_connect;
unique_ptr<pqxx::asyncconnection> async_connect;
try
{
switch (type) {
case ConnectionType::direct : {
connect = make_unique<pqxx::connection>(connOpts);
break;
}
case ConnectionType::lazy : {
lzy_connect = make_unique<pqxx::lazyconnection>(connOpts);
break;
}
case ConnectionType::async : {
async_connect = make_unique<pqxx::asyncconnection>(connOpts);
break;
}
} catch
...
}
Working answer provided in comment by 'some programmer dude'
Why not have a std::unique_ptr to pqxx::connection_base which is the common base class for all connection types? – Some programmer dude
Simplified code:
unique_ptr<pqxx::connection_base> base_connect;
try
{
switch (type) {
case ConnectionType::direct : {
base_connect = make_unique<pqxx::connection>(connOpts);
break;
}
case ConnectionType::lazy : {
base_connect = make_unique<pqxx::lazyconnection>(connOpts);
break;
}
case ConnectionType::async : {
base_connect = make_unique<pqxx::asyncconnection>(connOpts);
break;
}
default:
error += "No valid connection type supplied (direct | lazy | async)";
return false;
break;
}
I need to validate text within a wxTextControl as a float or an int (for starters). I will eventually need float > 0, float >= 0 etc etc. My idea was to create an enum defining all of my scenarios and create the val within a function. I'm having trouble getting started, as the declaration of the wxTextValidator throws an error.
enum class glValidate { glInt, glPosInt, gl0PosInt, glFloat, glPosFloat, gl0PosFloat, glString};
wxValidator GuiLib::CreateValidator(std::wstring* default_value, glValidate flag) {
wxArrayString numberArray;
numberArray.Add(wxT("0"));
numberArray.Add(wxT("1"));
numberArray.Add(wxT("2"));
numberArray.Add(wxT("3"));
numberArray.Add(wxT("4"));
numberArray.Add(wxT("5"));
numberArray.Add(wxT("6"));
numberArray.Add(wxT("7"));
numberArray.Add(wxT("8"));
numberArray.Add(wxT("9"));
wxTextValidator val(wxFILTER_NONE, default_value);
switch (flag) {
case glValidate::glInt:
numberArray.Add(wxT("-"));
val.SetStyle = wxFILTER_INCLUDE_LIST;
val.SetIncludes(numberArray);
break;
case glValidate::glPosInt:
val.SetStyle = wxFILTER_INCLUDE_LIST;
val.SetIncludes(numberArray);
break;
}
etc..
}
I recognize that even this simple scenario is busted because the glInt case would allow "123-456", but I think I can deal with that via an event handler once I get this part working. The problem is that I'm getting an error message stating
no instance of constructor "wxTextValidator::wxTextValidator" matches
the argument list
Did you try wxNumValidator< T > instead of your own?
I was fooled by Visual Studio. The problem with the above code is that default_value is wstring, when it needs to be wxString*. Visual Studio highlighted ```wxFILTER_NONE''', which lead me think the problem was there!
After rejigging to make fix the string param it works. Well it compiles - now I need to get the validation working as desired...
I am currently trying to figure out an alternative method for switch statements as the program I have the switch statements are getting really long and confusing. Therefore I thought it would be a good idea to use array of pointers to functions. I am using c++ and qt. But when I try and implement, I am getting the following error.
cannot convert 'CheckPl::comA' from type 'void (CheckPl::)()' to type 'void (*)()'
It would be much appreciated if someone would help me out with this or at least point me to correct direction.
[...] alternative method for switch statements as the program I have the switch statements are getting really long and confusing.
Extract each case block into a separate function; This way, the switch changes from a 10km long function to a dispatch function:
void dispatch_function()
{
switch(x)
{
case 1: do_case_1(); break;
...
case n: do_case_n(); break;
}
}
Therefore I thought it would be a good idea to use array of pointers to functions.
It's not a good idea (especially, not in the way you went about it - you are solving the xy problem). In C++, when you have a requirement for multiple functions that are called in similar conditions, you have the requirements for an abstract interface.
Your resulting client code should look like this:
std::vector<handlers> handlers; // filled with handler instances, one for each case
for(const auto& h: handlers) // replaces switch
if(h.fits_case(x)) // replaces case statement
{
h.do_case(x); // replaces case block
break;
}
It follows that your handler classes should inherit from a base class like this:
class handler_base
{
virtual bool fits_case(int x) = 0;
virtual void do_case(int x) = 0;
}
This is easy to understand (in both implementation and client code), it is modular, testable (you can test each case separately) and extensible (if you need a new case you only add the case and add it to the vector); It also doesn't use any pointers.
A pointer to a member function has to be stored in a variable of the appropriate type. A pointer to a member function is not compatible with a pointer to a function.
void (CheckPl::*mptr)() = &CheckPl::comA;
A pointer to a member function requires an instance to an object for invocation.
CheckPl c;
CheckPl *cp = &c;
(c.*mptr)();
(cp->*mptr)();
The hardest thing to remember about the above syntax is that the extra set of parentheses is required.
i use visual studi 2008. (c++)
in my switch case a wanted to create an object, but i doens't work.
is it right, that i can't create an object in a switch case?
if that's right,whats the best way to work around it,
a new method that's creates that object?
edit the code:
switch (causwahl){
case '1':
cAccount *oAccount = new cAccount (ID);
case '2' ....
I can't say for sure with such a vague question, but I'm guessing that you're doing something like this:
switch(foo)
{
case 1:
MyObject bar;
// ...
break;
case 2:
MyObject bar;
// ...
break;
}
This isn't allowed because each case statement has the same scope. You need to provide more scope if you want to use the same variable name:
switch(foo)
{
case 1:
{
MyObject bar;
// ...
break;
}
case 2:
{
MyObject bar;
// ...
break;
}
}
I suggest avoiding switch-case because of this and other problems. You can allow variable definitions by extra curly braces, but that looks messy and causes two levels of indentation. Other problems are that you can only use integer/enum values for cases, that the break statement cannot be used to break from a loop outside the switch. Forgetting to break is also a very common programming mistake that cannot be detected by the compiler (because it is still valid code) and it leads to hard to debug bugs.
Personally I only use switch-case with enum values, and even then never with a default label. This has the benefit of getting me a compile warning (from GCC) if not all possible values of the enum are handled.
There is nothing wrong with if-elses.
switch (choice)
{
case 1:
{
cout<<"\nBike object created********"<<endl;
Bike B1(2,4,50);
V=&B1;
V->Display_Details();
V->CallToll(persons);
break;
}
case 2:
{
cout<<"\n CAR object created********"<<endl;
Car C1(4,8,50);
V=&C1;
V->Display_Details();
V->CallToll(persons);
break;
}
default:
cout<<"You have entered an invalid choice...........Please Enter valid choice........"<<endl;
}