signal in C++: using a member function - c++

I have this problem with signal():
This code compiles fine:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void terminate( int param )
{
printf ( "Terminating program...\n" );
exit( 1 );
}
int main()
{
signal( SIGTERM, terminate );
return 0;
}
The following code, however, throws this error:
g++ -Wall -c -g goober.cpp
goober.cpp: In member function `void GOOBER::yarrgh()':
goober.cpp:5: error: argument of type `void (GOOBER::)(int)' does not match `
void (*)(int)'
make: *** [goober.o] Error 1
goober.h:
#ifndef GOOBER_H
#define GOOBER_H
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
using namespace std;
class GOOBER {
public:
GOOBER(){}
~GOOBER(){}
void yarrgh();
void terminate( int param );
};
#endif
goober.cpp:
#include "goober.h"
void GOOBER::yarrgh()
{
signal( SIGTERM, terminate );
}
void GOOBER::terminate( int param )
{
printf( "Terminating program...\n" );
exit( 1 );
}
driver.cpp:
#include "goober.h"
using namespace std;
int main()
{
GOOBER G;
G.yarrgh();
return 0;
}
I don't see any difference in the code, other than I'm calling signal() in a member. Any ideas what's wrong, and how to fix it?

You need to declare your terminate() function as static:
class GOOBER {
// ...
static void terminate(int param);
};
This is because that as a non-static member function, the terminate() function expects to be passed the (hidden) this parameter to point to some instance of the object. Since the signal mechanism doesn't know about this (or about anything much of C++), you need to use a static function so that there is no hidden this parameter.

I can tell you what's wrong:
You cannot use a non-static member function like a normal function pointer. Member functions always have an implicit this argument, which is provided (implicitly) by the caller. A C API cannot do this.

Terminate has to be a static function in the class.

Member function have different signature from normal function that not belong any class. However, static member function have the same signature with normal function. So, you could declare your terminate member function in GOOBER class as static.

Related

Decltype error - doesn't see method declaration

I'm trying to use decltype, but I got the same error every time when I was trying compile.
#include <iostream>
#include <cmath>
using namespace std;
class Polygon {
private:
double bok;
int katy;
public:
Polygon(int katy,double bok): katy (katy),bok (bok) {};
void scale(double s){ bok*=s;};
double area () const{
return (katy*(bok*bok))/(4.0*tan((M_PI/katy)));}};
int main(){
Polygon polygon(7,10.);
polygon.scale(2.);
cout<<polygon.area()<<endl;
if(!std::is_same<decltype(scale),void (Polygon*,double)>::value){
cout<<'p';
}
}
I got a error: "
error: ‘scale’ was not declared in this scope; did you mean ‘scalb’?
28 | if(!std::is_same<decltype(scale),void (Polygon*,double)>::value){
"
What's wrong?
You need to take a pointer to the member function and prefix it with the class scope in order to refer to it:
if (!std::is_same<decltype(&Polygon::scale), void(Polygon*, double)>::value) {
cout<<'p';
}
Be advised, however, that member function type is not a plain function pointer, as for each class there is special type defined within the class scope, which follows this pattern: ReturnType(ClassName::*)(args). Thus in your scenario, if you expect std::is_same to match the function, you should specify the conditional expression as follows:
std::is_same_v<
decltype(&Polygon::scale),
void(Polygon::*)(double)
>

std::async with non static member functions

I am trying to evaluate a part of my code asynchronously
#include <stdio.h>
#include <string>
#include <memory>
#include <future>
#include <map>
namespace IG
{
typedef std::map<uint, std::string> CadDef;
class FooFoo
{
CadDef foo()
{
CadDef cdef{};
cdef[1] = "aa";
return cdef;
}
};
}
int main()
{
auto ptr = std::make_unique<IG::FooFoo>();
std::future<IG::CadDef> resFut = std::async(ptr->foo);
auto res = resFut.get();
return 0;
}
But the code doesn't compile -
(On gcc)
error: invalid use of non-static member function ‘IG::CadDef IG::FooFoo::foo()’
(on msvc -- my main program, from where I abstracted the minimal example)
error C3867: 'IG::FooFoo::foo': non-standard syntax; use '&' to create a pointer to member
error C2672: 'std::async': no matching overloaded function found
error C2780: 'std::future<_Invoke_traits<void,decay<_Ty>::type,decay<_ArgTypes>::type...>::type> std::async(std::launch,_Fty &&,_ArgTypes &&...)': expects 3 arguments - 1 provided
Seems like MSVC is complaining that I have not used ptr->foo() but I am not sure.
What am I doing wrong?
You can use a lambda like following, using a policy*
auto handle = std::async(std::launch::async, [&ptr](){
return ptr->foo(); // Ofcourse make foo public in your snippet
});
auto res = handle.get();
*Not necessarily required
Async takes a function address as an argument, but it the function is a class-member function you have to bind it to the object which can invoke this function.
All functions (including methods) are moved to the code segment of the binary file.
That's why the sizeof(T) equals to sum of sizeof of all class data-members (including a virtual table pointer (vptr) if exists).
class A {void method() }; can be represented as void method(A* a) {}
Knowing all this information you should bind the method with the object
int main()
{
auto ptr = std::make_unique<IG::FooFoo>();
std::future<IG::CadDef> resFut = std::async(&IG::FooFoo::foo, ptr.get());
auto res = resFut.get();
return 0;
}

invincibility frame and take damage class

i am a beginner and i have already read a doc but i need to practice for learn and now i am stuck.
So i would like to do a class takeDommage for apply a number of dmg and activate a countdown for create the invincibility frame.
so i tryed this (see code under)
It's the first class i create alone so i don't understand what's wrong
main :
if(Collision::PixelPerfectTest(sprite_perso,sprite_ennemis))
{
std::cout<<"collision pp"<<std::endl;
takeDommage::prendreDegat(10);
std::cout<<pv<<std::endl;
}
takeDommage.h :
#ifndef TAKEDOMMAGE_H
#define TAKEDOMMAGE_H
#include <SFML/Graphics.hpp>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
class takeDommage
{
public:
takeDommage();
prendreDegat(int Dommage);
//virtual ~takeDommage();
protected:
sf::Clock takeDammageClock;
int Dommage;
private:
};
#endif // TAKEDOMMAGE_H
takeDommage.cpp
#include "takeDommage.h"
takeDommage::takeDommage()
{
}
void takeDommage::prendreDegat(int Dommage)
{
if(takeDammageClock.getElapsedTime().asSeconds()>=3)
{
std::cout << "bite" << std::endl;
pv -= Dommage;
takeDammageClock.restart();
}
}
error:
||=== Build: Debug in TheGameSFML (compiler: GNU GCC Compiler) ===|
E:\Work\Top_secret\code\TheGame\main.cpp||In function 'int main()':|
E:\Work\Top_secret\code\TheGame\main.cpp|168|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
E:\Work\Top_secret\code\TheGame\main.cpp|180|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
E:\Work\Top_secret\code\TheGame\main.cpp|217|error: cannot call member function 'int takeDommage::prendreDegat(int)' without object|
E:\Work\Top_secret\code\TheGame\main.cpp|156|warning: unused variable 'enemySpawnTimer' [-Wunused-variable]|
E:\Work\Top_secret\code\TheGame\src\takeDommage.cpp|8|error: prototype for 'void takeDommage::prendreDegat(int)' does not match any in class 'takeDommage'|
include\takeDommage.h|15|error: candidate is: int takeDommage::prendreDegat(int)|
||=== Build failed: 3 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|
you seem to be very new in c++. the compiler already telling you what's wrong with it.
error: cannot call member function 'int takeDommage::prendreDegat(int)' without object|
you need to instantiate (create) your object first. the way you accessing as if the takeDommage function is a static function which is not. its public a member function of takeDamage
assuming that you have instantiated your takeDommage class somewhere before the if statement call,
TakeDommage Obj;
...
...
if(Collision::PixelPerfectTest(sprite_perso,sprite_ennemis))
{
std::cout<<"collision pp"<<std::endl;
Obj.prendreDegat(10); //calling the prendredegat member function of Obj
std::cout<<pv<<std::endl;
}
in addition to that you are missing the return type void before the function name of prendreDegat
class takeDommage
{
public:
takeDommage();
//prendreDegat(int Dommage); //missing void
void prendreDegat(int Dommage); //correct way. which can be translated as Prendredegat returns nothing.

C++.Passing to functions.Syntax issue

I am pursuing some interest in c++ programming by way of self instruction. I am working on some basic stuff for now and am currently having issue getting my classes talking/instantiated?.
I am trying to get my main cpp file to compile alongside a header and call to some class functions through the main using a more efficient command method.
I am stuck and would appreciate some help. I will include both files. I am just trying to get a return value from the header by calling the function.
error:
main.cpp:6.21 error: cannot call member function 'void myClass::setNumber(int) without object
the code works when compiled with the main, so it is something with the 'scope resolution operator' i think. First is main.cpp
#include <iostream>
#include "myClass.h"
using namespace std;
int main(){
myClass::setNumber(6);
{
return number;
}
}
Then my header file myClass.h
// MyClass.h
#ifndef MYCLASS_H
#define MYCLASS_H
class myClass {
private:
int number;//declares the int 'number'
float numberFloat;//declares the float 'numberFloat
public:
void setNumber(int x) {
number = x;//wraps the argument "x" as "number"
}
void setNumberFloat(float x) {
numberFloat = x;
}
int getNumber() {//defines the function within the class.
number += 500;
return number;
}
float getNumberFloat() {//defines the function
numberFloat *= 1.07;
return numberFloat;
}
};
#endif
Any help?
The error message says everything:
cannot call member function 'void myClass::setNumber(int)' without object
You need to create an object first:
myClass obj;
then call the class method on that object:
obj.setNumber(6);
The value 6 will get assigned to the number field of the obj variable.

Why does compiler tries to pass a pointer to reference rather than pointer in this code snippet?

I have 5 files:
ExecutionStrategyInterface.h
ExecutorInterface.h
TaskCollectionInterface.h
TaskExecutor.h
TaskExecutor.cpp.
TaskExecutor implements the following member method:
void TaskExecutor::execute(TaskCollectionInterface* tci, const ExecutionStrategyInterface& es) {
es.execute(tci);
}
At compile time, the compiler calls a member method with a parameter of type pointer to a reference(i.e: mylib::core::TaskCollectionInterface*&).
TaskExecutor.cpp: In member function ‘virtual void mylib::core::TaskExecutor::execute(mylib::core::TaskCollectionInterface*, const mylib::core::ExecutionStrategyInterface&)’:
TaskExecutor.cpp:16: error: no matching function for call to ‘mylib::core::ExecutionStrategyInterface::execute(mylib::core::TaskCollectionInterface*&) const’
./././ExecutionStrategyInterface.h:24: note: candidates are: virtual void mylib::core::ExecutionStrategyInterface::execute(TaskCollectionInterface*) const
make: *** [TaskExecutor.o] Error 1
Can anyone explain me what is happening here please ?
Classes:
ExecutionStrategyInterface.h
#ifndef _EXECUTIONSTRATEGYINTERFACE_H_
#define _EXECUTIONSTRATEGYINTERFACE_H_
class TaskCollectionInterface;
namespace mylib { namespace core {
/**
* Interface for executing a strategy.
*/
class ExecutionStrategyInterface {
public:
/**
* Executes a strategy
*/
virtual void execute(TaskCollectionInterface* tci) const = 0;
};
}} // namespaces
#endif // _EXECUTIONSTRATEGYINTERFACE_H_
TaskCollectionInterface.h
#ifndef _TASKCOLLECTIONINTERFACE_H_
#define _TASKCOLLECTIONINTERFACE_H_
#include "./ExecutionStrategyInterface.h"
namespace mylib { namespace core {
/**
* Interface for a collection of tasks.
*/
class TaskCollectionInterface {
public:
~TaskCollectionInterface();
};
}} // namespaces
#endif // _TASKCOLLECTIONINTERFACE_H_
ExecutorInterface.h
#ifndef _EXECUTORINTERFACE_H_
#define _EXECUTORINTERFACE_H_
class ExecutionStrategyInterface;
class TaskCollectionInterface;
#include "./ExecutionStrategyInterface.h"
#include "./TaskCollectionInterface.h"
namespace mylib { namespace core {
/**
* Interface for an executor.
*/
class ExecutorInterface {
public:
virtual void execute(TaskCollectionInterface* tci, const ExecutionStrategyInterface& es) = 0;
~ExecutorInterface();
};
}} // namespaces
#endif // _EXECUTORINTERFACE_H_
TaskExecutor.h
#ifndef _TASKEXECUTOR_H_
#define _TASKEXECUTOR_H_
#include "./ExecutorInterface.h"
class TaskCollectionInterface;
class ExecutionStrategyInterface;
namespace mylib { namespace core {
/**
* Task Runner.
*/
class TaskExecutor: public ExecutorInterface {
public:
virtual void execute(TaskCollectionInterface* tci, const ExecutionStrategyInterface& es) = 0;
};
}} // namespaces
#endif // _TASKEXECUTOR_H_
TaskExecutor.cpp
#include "./TaskExecutor.h"
#include "./ExecutionStrategyInterface.h"
#include "./TaskCollectionInterface.h"
namespace mylib { namespace core {
void TaskExecutor::execute(TaskCollectionInterface* tci, const ExecutionStrategyInterface& es) {
es.execute(tci);
}
}} // namespaces
This is confusing because you are forward-declaring the class outside the namespace, so you are ending up with two different classes with the same name. You'll want something like this instead:
namespace mylib {
namespace core {
class TaskCollectionInterface;
class ExecutionStrategyInterface {
.
.
.
};
}
}
The way you have it now, your execute method is taking a pointer to ::TaskCollectionInterface instead of mylib::core::TaskCollectionInterface.
When gcc says type&, it's just its shorthand for saying that you are passing an lvalue so that you know that functions taking a non-const reference are viable candidates.
The problem that you have is that you have declared the method as taking a ::TaskCollectionInterface, but the error message indicates that you are attempting to pass a ::mylib::core::TaskCollectionInterface.
You have a declaration of ::mylib::core::TaskCollectionInterface in TaskCollectionInterface.h that masks the declaration of ::TaskCollectionInterface in the namespace mylib::core.
This is because you are passing a pointer TaskCollectionInterface* tci to the ExecutionStrategyInterface::execute method, while it wants a reference. So you have to dereference that pointer when passing it to that function:
void TaskExecutor::execute(TaskCollectionInterface* tci, const ExecutionStrategyInterface& es) {
es.execute(*tci);
}