What is the purpose of declaring a function as a pointer? - c++

I was looking through the source code of a project called CrossWindow-Graphics today when I saw an interesting function declaration. The code seemed to be declared as a function pointer. Here is a similar example I wrote.
#include <iostream>
using namespace std;
void (*Test())
{
cout << "Test Called!" << endl;
}
int main()
{
Test();
return 0;
}
My question is why does C++ allow this. I'd imagine it has something to do with function pointers. I remember that typedef is really just creating a variable and the name of the variable becomes the new type so I suppose this is just the same as creating a "variable" but it points to code. Even if that is the right idea, What is the purpose of that?

All you've really done here is add an extra pair of () that doesn't do anything.
We could write the same functin as
void* Test() { ... }
It's a function that returns a void*.
So the function should have a return statements where it returns a void pointer. Some compilers will warn about this as seen here.

Related

Segmentation fault on class when declared as pointer

So I’m in the process of creating an event style system, but this code breaks when I declare a connection as a pointer.
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
using namespace chrono_literals;
template<typename... Types>
struct Connection {
void Connect(void(*f)(Types...)) {
Callback = f;
}
void Fire(Types... Args) {
Callback(Args...);
}
private:
void(*Callback)(Types...);
};
int main() {
cout << boolalpha;
Connection<char>* event;
event->Connect([](char key){
cout << "Event fired!" << '\n';
cout << "Key: " << key << '\n';
});
event->Fire('a');
}
This code works when the connection isn’t a pointer, and instead of using the -> operator, I’d use use the regular . operator, but I’d like to declare them as pointers so I can use the -> .
One very strange thing to note is when I do something like this
Connection<char> e;
Connection<char>* event;
// ... rest of code
Then this actually runs, I don’t know why it’s like that.
You don't "declare a class as a pointer". That's not a thing. You have a class (which is a type), then you declare an instance of that class (i.e. an object). Optionally you can manage that object using pointers.
But you didn't actually create any instance. All you did was create a pointer, uninitialised, not pointing to anything, then tried to dereference it to use the object it points to… which doesn't exist.
There's no need for dynamic allocation here anyway; forget the pointer and just declare a nice Connection<Event>. Using pointers "because it looks nicer" is, to put it kindly, not the best way to write a C++ program.

Function-pointer when returning values

I am using C language to upgrade my coding skills.
I designed a simple program because I wanted to easily find the problems what I looked for and arrange the works when I handle many problems as shown in below.
Here is my header file
#pragma once
#ifndef PROBLEM_H
#define PROBLEM_H
namespace PROBLEM_1 { int do_main(); }
typedef int(*MAINFUNC)();
#endif
And below is my source file.
#include "problems.h"
#include <stdio.h>
#include <iostream>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
typedef int(*MAINFUNC)(void);
map<string, MAINFUNC> func_map;
void initialize_problem_map(void) {
func_map["problem_1"] = PROBLEM_1::do_main;
}
namespace PROBLEM_1 {
int do_main(void) {
cout << "hi" << endl;
return 1;
}
}
int main(void) {
string problem;
initialize_problem_map();
cin >> problem;
if (func_map.find(problem) != func_map.end())
return (*(func_map[problem]))();
return -1;
}
If I input "PROBLEM_1" then, the do_main functions in namespace PROBLEM_1 will be executed. I think that this design helps me organize multiple coding problems.
However, my question is about these two code lines as below.
if (func_map.find(problem) != func_map.end())
return (*(func_map[problem]))();
As you can see, the main fucntion's return type is "int". However, in the if-clause, i think that it return function-pointer. Therefore, I thought that those returning behavior is mismatched with the main function's return type. But, to my surprise, it worked well.
Could u explain this procedures regarding returning types?
func_map[problem], indeed, results in a function pointer. Applying the operator () on it, the function is invoked and the expression results in an int. Dereferencing a function pointer before its invocation is optional. This is symmetric with an optional address taking on a function name for initializing function pointers.
Indeed
func_map[problem]
is a pointer. However, you dereference the pointer with *:
*(func_map[problem])
and call function by adding ():
(*(func_map[problem]))()
which returns "int".
find returns an iterator; if this iterator is end, then the problem does not exist in the map; Because it is not end, it exists, then in the return line the pointer function obtained with [] is used to call it.

What is the point of MyType(myVar) declaration in C++?

In c++11 standard we can declare variable in an unusual way. We can declare myVar as int(myVar); instead of int myVar. What is the point of this?
#include <iostream>
using namespace std;
int main() {
int(myVar);
myVar = 1000;
cout << myVar << endl;
return 0;
}
UPD Actually there is a certain reason why I asked this. What looked innocent just stopped to compile when we tried to port some code from MSVC C++03 to GCC C++11.
Here is an example
#include <iostream>
using namespace std;
struct MyAssert
{
MyAssert(bool)
{
}
};
#define ASSERT(cond) MyAssert(cond)
void func(void* ptr)
{
ASSERT(ptr); // error: declaration of ‘MyAssert ptr’
// shadows a parameter #define ASSERT(cond) MyAssert(cond)
}
int main()
{
func(nullptr);
return 0;
}
Sure. I can even do this:
int (main)()
{
}
Parentheses serve to group things in C and C++. They often do not carry additional meaning beyond grouping. Function calls/declarations/definitions are a bit special, but if you need convincing that we should not be allowed to omit them there, just look at Ruby, where parentheses are optional in function calls.
There is not necessarily a point to it. But sometimes being able to slap on some theoretically unnecessary parentheses helps make code easier to read. Not in your particular example, and not in mine, of course.
#include <typeinfo>
#include <iostream>
int main(void)
{
int *first_var[2];
int (*second_var)[2];
std::cout << typeid(first_var).name() << std::endl;
std::cout << typeid(second_var).name() << std::endl;
return 0;
}
Running this on my machine gives :
A2_Pi
PA2_i
The parenthesis in the declaration mostly serve the same purpose they do everywhere, group things that should be together regardless of the default priority order of the language.
Of course parenthesis with only one element inside is equivalent to just typing that element except in cases where parenthesis are mandatory (e.g function calls).
C++ does not break backward compatibility if it can help it.
The C that it was developed from had this syntax. So C++ inherited it.
A side effect of this backward compatibility are the vexing parse problems. They have not proved sufficiently vexing to justify breaking backward compatibility.

Why prototype is required even without any class declaration?

If I just do it:
Ex1:
#include <iostream>
int main()
{
//try to call doSomething function
doSomething();
}
void doSomething()
{
std::cout << "Call me now!" << std::endl;
}
I get compilation error! Because the compile doesn´t know what is "doSomething".
But if I change the position of doSomething to come in first place, the program compiles successfully.
Ex2:
#include <iostream>
void doSomething()
{
std::cout << "Call me now!" << std::endl;
}
int main()
{
//try to call doSomething function
doSomething();
}
I can declare prototype to be like this:
Ex3:
#include <iostream>
void doSomething(void);
int main()
{
//try to call doSomething function
doSomething();
}
void doSomething()
{
std::cout << "Call me now!" << std::endl;
}
But why the first example does not work? Why I even have to declare a prototype or call functions first and main function at last?
Thanks!
You can't call a function without the compiler having seen either the definition or a declaration, first -- simple as that. A prototype or the actual definition must appear before a call.
Because the compiler hasn't seen doSomething before it's used.
Either you must prototype it, or define it first, so that the compiler knows how to analyze the usage of it.
This is a legacy from C. C is a single pass language which means that it has to do everything by only reading the file once. To be able to call a function without a forward declaration/prototype would require reading the file twice; The first time to find all the function signatures and the second time to actually compile.
C++ kept this requirement for features that were part of C, such as free functions and global variables. However classes are new to C++ and there was no need to keep the old way of doing things. So within a single class definition, multi-pass compilation is used. That's why you can do this:
class MyClass {
void foo() {bar();}
void bar() {}
};
But you can't do what you listed in your question.

How does the Visual C++ compiler pass the this ptr to the called function?

I'm learning C++ using Eckel's "Thinking in C++". It states the following:
If a class contains virtual methods, a virtual function table is created for that class etc. The workings of the function table are explained roughly. (I know a vtable is not mandatory, but Visual C++ creates one.)
The calling object is passed to the called function as an argument. (This might not be true for Visual C++ (or any compiler).) I'm trying to find out how VC++ passes the calling object to the function.
To test both points in Visual C++, I've created the following class (using Visual Studio 2010, WinXP Home 32bit):
ByteExaminer.h:
#pragma once
class ByteExaminer
{
public:
short b[2];
ByteExaminer(void);
virtual void f() const;
virtual void g() const;
void bruteFG();
};
ByteExaminer.cpp:
#include "StdAfx.h"
#include "ByteExaminer.h"
using namespace std;
ByteExaminer::ByteExaminer(void)
{
b[0] = 25;
b[1] = 26;
}
void ByteExaminer::f(void) const
{
cout << "virtual f(); b[0]: " << hex << b[0] << endl;
}
void ByteExaminer::g(void) const
{
cout << "virtual g(); b[1]: " << hex << b[1] << endl;
}
void ByteExaminer::bruteFG(void)
{
int *mem = reinterpret_cast<int*>(this);
void (*fg[])(ByteExaminer*) = { (void (*)(ByteExaminer*))(*((int *)*mem)), (void (*)(ByteExaminer*))(*((int *)(*mem + 4))) };
fg[0](this);
fg[1](this);
}
The navigation through the vtable in bruteFG() works - when I call fg[0](this), f() is called. What does NOT work, however, is the passing of this to the function - meaning that this->b[0] is not printed correctly (garbage comes out instead. I'm actually lucky this doesn't produce a segfault).
So the actual output for
ByteExaminer be;
be.bruteFG();
is:
virtual f(); b[0]: 1307
virtual g(); b[1]: 0
So how should I proceed to get the correct result? How are the this pointers passed to functions in VC++?
(Nota bene: I'm NOT going to program this way seriously, ever. This is "for the lulz"; or for the learning experience. So don't try to convert me to proper C++ianity :))
Member functions in Visual Studio have a special calling convention, __thiscall, where this is passed in a special register. Which one, I don't recall, but MSDN will say. You will have to go down to assembler if you want to call a function pointer which is in a vtable.
Of course, your code exhibits massively undefined behaviour- it's only OK to alias an object using a char or unsigned char pointer, and definitely not an int pointer- even ignoring the whole vtable assumptions thing.
OK using DeadMG's hint I've found a way without using assembler:
1) Remove the ByteExaminer* arg from the functions in the fg[] array
2) Add a function void callfunc(void (*)()); to ByteExaminer:
void ByteExaminer::callfunc(void (*func)())
{
func();
}
... this apparently works because func() is the first thing to be used in callfunc, so ecx is apparently not changed before. But this is a dirty trick (as you can see in the code above, I'm always on the hunt for clean code). I'm still looking for better ways.