I created a class named result_line and have been having problems with it's constructor. That is that it wasn't being assigned the expected values.
I have since created a similar, but more frugal, class named rsltline and this appears to work.
Here's the 2 classes :-
result_line
class result_line {
private:
HWND rwnd;
int result_flags;
int result_extraflags;
public:
result_line(HWND, int, int);
~result_line();
HWND result_lineGetHWND();
void result_lineSetHWND(HWND);
int result_lineGetFlags();
int result_lineGetExtraFlags();
DINT result_lineGetBothFlags();
void result_lineSetFlags(int);
void result_lineSetExtraFlags(int);
void result_lineSetBothFlags(int,int);
void result_lineSetBothFlags(DINT);
};
// Constructor for result_line(HWND) and result_line(HWND, result_flag)
result_line::result_line(HWND rwnd, int result_flags, int result_extraflags) {
rwnd = rwnd;
result_flags = 30;
result_extraflags = 40;
}
result_line::~result_line() {}
HWND result_line::result_lineGetHWND() { return rwnd; }
int result_line::result_lineGetFlags() { return result_flags; }
int result_line::result_lineGetExtraFlags() { return result_extraflags; }
DINT result_line::result_lineGetBothFlags() { return DINT(result_flags,result_extraflags); }
void result_line::result_lineSetHWND(HWND rwnd) { rwnd = rwnd; }
void result_line::result_lineSetFlags(int result_flags) { result_flags = result_flags; }
void result_line::result_lineSetExtraFlags(int result_extraflags) { result_extraflags = result_extraflags; }
void result_line::result_lineSetBothFlags(int result_flags, int result_extraflags) {
result_flags = result_flags;
result_extraflags = result_extraflags;
}
void result_line::result_lineSetBothFlags(DINT dint) {
result_flags = dint.aint;
result_extraflags = dint.bint;
}
rsltline
class rsltline {
private:
HWND rlHWND;
int rlflag1;
int rlflag2;
public:
rsltline(HWND, int, int);
HWND rsltlineGetHWND();
int rsltlineGetFlag1();
int rsltlineGetFlag2();
};
rsltline::rsltline(HWND hwnd, int rf1, int rf2) {
rlHWND = hwnd;
rlflag1 = rf1;
rlflag2 = rf2;
}
HWND rsltline::rsltlineGetHWND() { return rlHWND; }
int rsltline::rsltlineGetFlag1() { return rlflag1; }
int rsltline::rsltlineGetFlag2() { return rlflag2; }
I have the following code to create and then display instances using the two classes (the last using the rsltline class as opposed to the result_line class, as used by the first two) :-
result_line foo = result_line(0,3,6);
std::cout << "HWND=" << foo.result_lineGetHWND() <<
"\tFLAGS=" << foo.result_lineGetFlags() <<
"\tEXTRAFLAGS=" << foo.result_lineGetExtraFlags() <<
std::endl;
result_line testrslt = result_line((HWND) 0,100,200);
std::cout << "HWND=" << testrslt.result_lineGetHWND() <<
"\tFLAGS=" << testrslt.result_lineGetFlags() <<
"\tEXTRAFLAGS=" << testrslt.result_lineGetExtraFlags() <<
std::endl;
rsltline myrsltline = rsltline((HWND)2,4,6);
std::cout << "HWND=" << myrsltline.rsltlineGetHWND() <<
"\tFLAGS=" << myrsltline.rsltlineGetFlag1() <<
"\tEXTRAFLAGS=" << myrsltline.rsltlineGetFlag2() <<
std::endl;
The first two return Unexpected Results, the last using the rsltline class works as expected. The results are:-
HWND=0 FLAGS=0 EXTRAFLAGS=0
HWND=0 FLAGS=1997196755 EXTRAFLAGS=0
HWND=0x2 FLAGS=4 EXTRAFLAGS=6
Process returned 0 (0x0) execution time : 35.007 s Press any key to
continue.
The only thing that I can think that may be causing this is the naming of the former. Although, perhaps it's simply a case of me needing to visit an optician :).
Lets take a closer look at the result_line constructor:
// Constructor for result_line(HWND) and result_line(HWND, result_flag)
result_line::result_line(HWND rwnd, int result_flags, int result_extraflags) {
rwnd = rwnd;
result_flags = 30;
result_extraflags = 40;
}
You declare a set of arguments, named rwnd, result_flags and result_extraflags. These are the same a local variables inside the constructor function body, and therefore shadows the member variables with the same name.
What happens is that you assign values to the local variables (the arguments), and not the member variables.
There are three solutions: Either use different names for the arguments, or prefix the member variables with this->, or use a constructor initializer list:
result_line::result_line(HWND rwnd, int result_flags, int result_extraflags)
: rwnd{rwnd}, result_flags{30], result_extraflags{40}
{
// Empty body
}
In the constructor body of result_line, you have written this:
rwnd = rwnd;
which is self-assignment of the parameter. The member remains uninitialized (like the other two members as well). You wanted to write this:
this->rwnd = rwnd;
That is one problem I can see in your code, which can be fixed as above — however, it is best to use member-initialization-list:
result_line::result_line(HWND rwnd, int result_flags, int result_extraflags)
: rwnd(rwnd),
result_flags(result_flags),
result_extraflags(result_extraflags)
{
}
Here, members are initialized in the form of X(Y) — X is a member and Y is a parameter; X and Y could be the same name, but they would continue to represent what they are — member and parameter.
Related
I have a bunch of derived structs. Is there any way for me to access the derived width without casting?
If I do this, I get 1s and not 42 and 13:
#include <iostream>
#include <deque>
using namespace std;
struct BaseParams {
virtual ~BaseParams() {}
int width = 1;
};
struct VectorParams : BaseParams {
int width = 42;
};
struct MatrixParams : BaseParams {
int width = 13;
};
int main()
{
std::deque<BaseParams *> params;
VectorParams *vectorParams = new VectorParams;
MatrixParams *matrixParams = new MatrixParams;
params.push_back(vectorParams);
params.push_back(matrixParams);
for (auto ¶m : params) {
std::cout << param->width << std::endl;
}
// Don't want to do this
// for (auto ¶m : params) {
// MatrixParams *matrixParams = dynamic_cast<MatrixParams *>(param);
// if (matrixParams)
// std::cout << matrixParams->width << std::endl;
// VectorParams *vectorParams = dynamic_cast<VectorParams *>(param);
// if (vectorParams)
// std::cout << vectorParams->width << std::endl;
// }
return 0;
}
If possible, I want to avoid casting because I have so many derived structs.
To overwrite the width in BaseParams, instead of making a new variable, you can give VectorParams a constructor like this:
struct VectorParams : BaseParams {
VectorParams() {
width = 42;
}
};
In fact constructors are always how variables are set in new objects. When you write
struct BaseParams {
virtual ~BaseParams() {}
int width = 1;
};
the compiler actually turns it into a constructor, similar to
struct BaseParams {
virtual ~BaseParams() {}
int width;
BaseParams() {
width = 1;
}
};
I am trying to figure out how to use GetAsyncKeyState with private attributes forward and backwards from a base class. I need to be able to reset GetAsyncKeyState to other keypresses. Any idea?
Maybe overriding forward and backwards with other keypresses?
#include <iostream>
#include <windows.h>
#include <string>
#include<conio.h>
using namespace std;
bool reset_defaults = false;
class Base {
protected: // OR private
int forward = VK_UP, backwards = VK_DOWN;
public: //...
}
////////////
class Move : public Base {
public:
Base def;
int move() {
while (true) {
if (GetAsyncKeyState(forward) < 0){
cout << ("forward >>>\n");
if (GetAsyncKeyState(forward) == 0){
cout << ("Stopped\n");
}
}
if (GetAsyncKeyState(VK_SPACE) < 0){break;}
}
}
int main() {
Move move;
move.move();
}
Sorry, but I don't think I understand the whole logic of this yet.
PS UPDATE:
How can I override baseKeys values:
class MovementKeys {
protected:
int baseKeys(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right){
default_key_forward = VK_UP;
default_key_backward = VK_DOWN;
default_key_left = VK_LEFT;
default_key_right = VK_RIGHT;
}
public:
int definedCommand(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right) {
while (reset_defaults == false)
{
cout << ("HERE 1 \n");
if (GetAsyncKeyState(default_key_forward) < 0)
{
cout << ("forward\n");
}
if (GetAsyncKeyState(default_key_backward) < 0)
{
court << ("backwards\n");
}
if (GetAsyncKeyState(default_key_left) < 0)
{
cout << ("left\n");
}
if (GetAsyncKeyState(default_key_right) < 0)
{
cout << ("right\n");
}
if (GetAsyncKeyState(VK_SPACE) < 0) { break; }
}
return 0;
}
int derived_newKeys(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right) {
return baseKeys(default_key_forward, default_key_backward, default_key_left, default_key_right);
}
You probably want to use member variables to store the keys. Instead of deriving the class with new keys, you set the variables in constructors (to default or to changed values) and can also change the key assignment later on.
You probably want to create a separate class, which reacts on the events.
#include <iostream>
#include <windows.h>
#include <conio.h>
using namespace std;
class World {
public:
void forward() { y--; };
void backward() { y++; };
void left() { x--; };
void right() { x++; };
private:
int x = 0;
int y = 0;
};
class MovementKeys {
// member variables
private:
// keep reference to world instead of copy; main() has to make sure World object outlives MovementKeys object
World& world;
int key_forward;
int key_backward;
int key_left;
int key_right;
public:
// constructor, which only sets world, but keeps the keys at their default settings
//
// world has to be initialized before the constructor function body
// as references have no default value
// put initialization in member initialization list
MovementKeys(World& w) : world(w)
{
key_forward = VK_UP;
key_backward = VK_DOWN;
key_left = VK_LEFT;
key_right = VK_RIGHT;
}
// constructor which modifies keys
MovementKeys(World& w, int change_key_forward, int change_key_backward, int change_key_left, int change_key_right) : world(w)
{
changeKeys(change_key_forward, change_key_backward, change_key_left, change_key_right);
}
// command loop controlled by keys
int definedCommand()
{
while (true)
{
cout << ("HERE 1 \n");
if (GetAsyncKeyState(key_forward) < 0)
{
cout << ("forward\n");
world.forward();
}
if (GetAsyncKeyState(key_backward) < 0)
{
cout << ("backwards\n");
world.backward();
}
if (GetAsyncKeyState(key_left) < 0)
{
cout << ("left\n");
world.left();
}
if (GetAsyncKeyState(key_right) < 0)
{
cout << ("right\n");
world.right();
}
// optionally change keys from within while loop
if (GetAsyncKeyState(VK_BACK) < 0)
{
key_forward = VK_RETURN;
}
if (GetAsyncKeyState(VK_SPACE) < 0)
{
break;
}
}
return 0;
}
// function for changing the keys stored in the member variables
// can be called by constructor or externally
void changeKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right)
{
key_forward = change_key_forward;
key_backward = change_key_backward;
key_left = change_key_left;
key_right = change_key_right;
}
};
int main()
{
World earth;
// use default keys, declares local variable and constructs MovementKeys object called move
MovementKeys move(earth);
move.definedCommand();
// use custom keys, share same world, declares local variable and constructs MovementKeys object called move2
// static_cast<int>() with a letter in a literal char parameter works, because the VK_ values of letter keys are the actual ASCII values (on purpose by Microsoft, I would assume)
MovementKeys move2(earth, static_cast<int>('W'), static_cast<int>('S'), static_cast<int>('A'), static_cast<int>('D'));
move2.definedCommand();
// change keys in move2
move2.changeKeys(VK_LBUTTON, VK_RBUTTON, VK_CONTROL, VK_SHIFT);
move2.definedCommand();
// run first one again for the fun of it
move.definedCommand();
}
Alternatively passing World& only, where it is used in definedCommand (and at the same time be able to use several worlds):
class World {
// ...
};
class MovementKeys {
// member variables without world, we can also put default value here
private:
int key_forward = VK_UP;
int key_backward = VK_DOWN;
int key_left = VK_LEFT;
int key_right = VK_RIGHT;
public:
// default constructor with no parameters, delegate to other constructor
// delegating not necessary, as the default values are set above anyway; just demonstrating various techniques for initializing member variables
MovementKeys() : MovementKeys(VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT) {};
// constructor which modifies keys, put everything in member initialization list
MovementKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right) : key_forward(change_key_forward), key_backward(change_key_backward), key_left(change_key_left), key_right(change_key_right) {};
// command loop controlled by keys, pass World& here as parameter
int definedCommand(World& world)
{
while (true)
{
// ...
}
return 0;
}
void changeKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right)
{
// ...
}
};
int main()
{
// use default keys, declares local variable and constructs MovementKeys object called move
MovementKeys move;
// use custom keys, declares local variable and constructs MovementKeys object called move2
MovementKeys move2(static_cast<int>('W'), static_cast<int>('S'), static_cast<int>('A'), static_cast<int>('D'));
MovementKeys defaultMenuKeys;
World earth;
World moon;
World menu; // between moving in worlds, we want to control some settings in a menu
move.definedCommand(earth);
move2.definedCommand(earth);
move2.definedCommand(moon);
// change keys in move2
move2.changeKeys(VK_LBUTTON, VK_RBUTTON, VK_CONTROL, VK_SHIFT);
move2.definedCommand(earth);
defaultMenuKeys.definedCommand(menu);
// run first one again for the fun of it
move.definedCommand(moon);
}
You can introduce a (class) enum with a list of the states, why definedCommand() returns:
// outside or can be put into MovementKeys and henceforth used as MovementKeys::ReturnReason
class enum ReturnReason { EXIT, NEWKEYS, SHOWMENU, SWITCHWORLD };
// in class MovementKeys
ReturnReason definedCommand() {
// ...
return NEWKEYS;
// ...
return EXIT;
// ...
return SHOWMENU;
// ...
}
// in main()
ReturnReason r = definedCommand();
if (r == NEWKEYS)
move2.changeKeys(...);
else if (r == EXIT)
return 0;
If you use that 'trick' to also control the menu, it could make sense to use virtual inheritance now for World. As the normal World and the menu World probably react quite differently. (The base class (ancestor) would be World, which is recognized by MovementKeys. Your actual Worlds are objects of derived (children) classes, with more specific behaviour.
definedCommand then can be called and run with any derived class of the base class World.
I have tried to call the class function computeCivIndex() from another class I have defined but it says that there was an undefined reference to LocationData::computeCivIndex(string, int, int, float, float) and a defined an unused funciton computeCivIndex(string int, int, float, float) in my LocationData.cpp
And I used g++ -Wall -W LocationData.h LocationData.cpp PointTwoD.h PointTwoD.cpp MissionPlan.cpp -o myProg.o to compile.
LocationData.h
static float computeCivIndex( string sunType_, int noOfEarthLikePlanets_, int noOfEarthLikeMoons_, float aveParticulateDensity_, float avePlasmaDensity_ ); /*calculate the possibility of life in the star system*/
};
LocationData.cpp
static float computeCivIndex( string sunType_, int noOfEarthLikePlanets_, int noOfEarthLikeMoons_, float aveParticulateDensity_, float avePlasmaDensity_ )
{
int sunTypePercent = 0;
float civIndex;
// convert string suntype to suntype percent
if (sunType_ == "Type O")
{
sunTypePercent = 30;
}
if (sunType_ == "Type B")
{
sunTypePercent = 45;
}
if (sunType_ == "Type A")
{
sunTypePercent = 60;
}
if (sunType_ == "Type F")
{
sunTypePercent = 75;
}
if (sunType_ == "Type G")
{
sunTypePercent = 90;
}
if (sunType_ == "Type K")
{
sunTypePercent = 80;
}
if (sunType_ == "Type M")
{
sunTypePercent = 70;
}
//compute the CivIndex
civIndex = ( (sunTypePercent/100) - (aveParticulateDensity_ + avePlasmaDensity_)/200 ) *
(noOfEarthLikePlanets_ + noOfEarthLikeMoons_);
return civIndex;
}
MissionPlan.cpp
float computeCivIndex[arraySize];
//compute civ index for all stored records
for (int i = 0; i < (entryNo+1); i++)
{
string suntype = locData[i].getSunType();
int earthlikeplanets = locData[i].getNoOfEarthLikePlanets();
int earthlikemoons = locData[i].getNoOfEarthLikeMoons();
float partdensity = locData[i].getAveParticulateDensity();
float plasdensity = locData[i].getAvePlasmaDensity();
locData[i].computeCivIndex(suntype,earthlikeplanets, earthlikemoons , partdensity, plasdensity);
point2d[i].setCivIndex(computeCivIndex[i]);
}
cout << "Computation Completed! ( " << entryNo <<" records were updated )" << endl;
That is because you have not implemented the function!
You need to qualify the function appropriately in the implementation to tell the compiler that you are actually implementing the class functions:
SomeClass.h:
class SomeClass
{
void someFunction();
static void someStaticFunction();
};
SomeClass.cpp:
void SomeClass::someFunction() { }
void SomeClass::someStaticFunction() { } // static must not be repeated!
If you do simply
void someFunction() { }
static void someStaticFunction() { }
you define two additional functions at namespace scope, not at class scope as you intended. By declaring them static, you additionally limit accessibility to from within the .cpp file they are defined in, so won't be found when compiling other .cpp files.
Be aware that static within a class has a completely different meaning than at global scope (and another different meaning within a function body) - Coming to that later. First, another error, though:
locData[i].computeCivIndex(suntype,earthlikeplanets, earthlikemoons , partdensity, plasdensity);
Via operator. (or operator-> on pointers), you can only call non-static functions (this is different from Java), static functions need to be called with class scope:
LocationData::computeCivIndex(suntype,earthlikeplanets, earthlikemoons, partdensity, plasdensity);
Meaning of static at different scopes:
class SomeClass
{
static void f(); // static class function as you know
};
static void anotherF(); // free/global function - static limits accessibility!
void yetAnotherF()
{
static int n = 0; // see below
}
static void anotherF(); is the C way to limit acessibility - the C++ variant of is placing the function into an anonymous namespace:
namespace
{
void anotherF() { }
}
Finally: static within functions: This way, you declare some kind of global variable that is only accessible from within the function. It is initialised only the first time you call the function, and the previous value of will be available on all subsequent calls:
void f()
{
static int x = 0;
printf("%d ", ++x);
}
int main()
{
f();
f();
f();
return 0;
}
Output will be: 1 2 3.
More details you find here.
I am having trouble in initializing an array of structures with a function pointer as a member in it.
class Record
{
private:
typedef void (*display_fn_t) ();
struct record {
int a;
display_fn_t disp;
};
static const record rec[];
void disp1() { cout << "Display 1 with a string to display" << endl; }
void disp2() { cout << "Display 2 with an integer to display" << endl; }
public:
int find() { /* logic to find the record comes here */ }
void display() {
for (int i = 0; i < 2; i++) {
rec[i].disp();
}
}
}
const Record::record Record::rec[] = {
{ 10, disp1 },
{ 11, disp2 }
};
int main()
{
Record r;
if (r.find())
r.display();
return 0;
}
When I compile the above code, I am getting the following compilation error:
mca_record.cpp:56: error: argument of type ‘void (Record::)()’ does
not match ‘void (*)()’
Your syntax is wrong and isn't using the appropriate operators.
Fixing a multitude of syntax errors, and stripping out the unrelated find operation, then utilizing proper member function pointers and operator ->* gives the following (one of several ways to do this):
#include <iostream>
class Record
{
private:
typedef void (Record::*display_memfn_t)();
struct record
{
int a;
display_memfn_t disp;
};
static const record rec[];
void disp1() { std::cout << "Display 1 with a string to display" << std::endl; }
void disp2() { std::cout << "Display 2 with an integer to display" << std::endl; }
public:
void display();
};
const Record::record Record::rec[] =
{
{ 10, &Record::disp1 },
{ 11, &Record::disp2 }
};
void Record::display()
{
for (size_t i=0; i<sizeof rec/sizeof*rec; ++i)
(this->*(rec[i].disp))();
}
int main()
{
Record r;
r.display();
return 0;
}
Output
Display 1 with a string to display
Display 2 with an integer to display
Compare it to your existing code, and not in particular that pointers to member functions are not simply pointers to functions. They require different handling and generally different operators to utilize. See here for different methods of member access (both variable and function).
Best of luck.
To make the call work you must invoke it like this:
for (int i = 0; i < 2; i++) {
(*rec[i].disp)();
}
And initialize the table this way:
const Record::record Record::rec[] = {
{ 10, &Record::disp1 },
{ 11, &Record::disp2 }
};
class Foo {
public:
Foo() { do_something = &Foo::func_x; }
int (Foo::*do_something)(int); // function pointer to class member function
void setFunc(bool e) { do_something = e ? &Foo::func_x : &Foo::func_y; }
private:
int func_x(int m) { return m *= 5; }
int func_y(int n) { return n *= 6; }
};
int
main()
{
Foo f;
f.setFunc(false);
return (f.*do_something)(5); // <- Not ok. Compile error.
}
How can I get this to work?
class A{
public:
typedef int (A::*method)();
method p;
A(){
p = &A::foo;
(this->*p)(); // <- trick 1, inner call
}
int foo(){
printf("foo\n");
return 0;
}
};
void main()
{
A a;
(a.*a.p)(); // <- trick 2, outer call
}
The line you want is
return (f.*f.do_something)(5);
(That compiles -- I've tried it)
"*f.do_something" refers to the pointer itself --- "f" tells us where to get the do_something value from. But we still need to give an object that will be the this pointer when we call the function. That's why we need the "f." prefix.
class A {
int var;
int var2;
public:
void setVar(int v);
int getVar();
void setVar2(int v);
int getVar2();
typedef int (A::*_fVar)();
_fVar fvar;
void setFvar(_fVar afvar) { fvar = afvar; }
void insideCall() { (this->*fvar)(); }
};
void A::setVar(int v)
{
var = v;
}
int A::getVar()
{
std::cout << "A::getVar() is called. var = " << var << std::endl;
return var;
}
void A::setVar2(int v2)
{
var2 = v2;
}
int A::getVar2()
{
std::cout << "A::getVar2() is called. var2 = " << var2 << std::endl;
return var2;
}
int main()
{
A a;
a.setVar(3);
a.setVar2(5);
// a.fvar = &A::getVar;
a.setFvar(&A::getVar);
(a.*a.fvar)();
a.setFvar(&A::getVar2);
(a.*a.fvar)();
a.setFvar(&A::getVar);
a.insideCall();
a.setFvar(&A::getVar2);
a.insideCall();
return 0;
}
I extended Nick Dandoulakis's answer. Thank you.
I added a function which set the member function pointer from outside of the class. I added another function which can be called from outside to show inner call of member function pointer.
Try (f.*do_something)(5);
#include<iostream>
using namespace std;
class A {
public:
void hello()
{
cout << "hello" << endl;
};
int x = 0;
};
void main(void)
{
//pointer
A * a = new A;
void(A::*pfun)() = &A::hello;
int A::*v1 = &A::x;
(a->*pfun)();
a->*v1 = 100;
cout << a->*v1 << endl << endl;
//-----------------------------
A b;
void(A::*fun)() = &A::hello;
int A::*v2 = &A::x;
(b.*fun)();
b.*v2 = 200;
cout << b.*v2 << endl;
}
I think calling a non static member of the class could also be done using a static member function.