I have some task: There are a lot of .cpp files, so I must find all the declarations of global variables in each of them. So I have, for example, this part of code:
class word {
public:
word(string code0, string text0, int weight0) : code(code0), text(text0),
weight(weight0), index(word::num) {};
friend bool operator<(word w1, word w2);
friend ostream &operator<<(ostream &stream, word w);
friend bool wordWithCode::operator()(const word &w);
static bool convertChars(char *inp, char *out);
inline bool checkCode(char *check) { return !strcmp(code.c_str(),check); };
inline const char* getText() { return text.c_str(); };
inline void useIt(set< word >::iterator &i) {
cout << this->text;
if (code[0]!='1') {
word::num++;
word::words.insert(word(this->code,this->text,this->weight+1));
word::words.erase(i);
}
return;
};
static set< word > words;
string code;
string text;
int weight;
static int num;
private:
int index;
};
int word::num = 0;
set< word > word::words;
int main(){
...
return 0;
}
So my question: Is the static variables word::num and word::words are global? And how to correctly identify their names(just "num" or "word::num")?
Yes, they're single global variables and you reference them outside of word's functions as word::num and word::words. Inside word's functions you can reference them just as num and words
Related
This is part of a C++ program based on the Alternative Vote electoral method, using VS2015. I have a class for Party
#pragma once
#ifndef _PARTY_H
#define _PARTY_H
#include <string>
class Party {
public:
Party();
~Party();
Party(std::string n, int pos);
void reset();
void upTotal();
int getPosition();
std::string getName();
int getVotes();
private:
std::string name;
int votes;
int position;
};
#endif
and
#include <iostream>
#include "Party.h"
using namespace std;
Party::Party() {}
Party::~Party() {}
Party::Party(string n, int p) {
name = n;
position = p;
}
void Party::reset() {
votes = 0;
}
void Party::upTotal() {
votes += 1;
}
int Party::getPosition() {
return position;
}
string Party::getName() {
return name;
};
int Party::getVotes() {
return votes;
}
I tried to sort on votes received using (calculated from ballot papers elsewhere in the program
void sortParties() {
sort(parties.begin(), parties.end(), [](const auto& a, const auto& b)
{
return a.getVotes() < b.getVotes();
});
}
which returned illegal operand errors. Moving the variables from private to public and writing the following did work
void sortParties() {
sort(parties.begin(), parties.end(), [](const auto& a, const auto& b)
{
return a.votes < b.votes;
});
}
which gets it working, but I want to write it with proper encapsulation using private variables and an accessor for votes. Do I need to overload somehow, or convert type?
You have the following functions defined:
int getPosition();
std::string getName();
int getVotes();
They should probably all be const; ie
int getPosition() const;
std::string getName() const;
int getVotes() const;
This will allow you to call the functions from your const object at
sort(parties.begin(), parties.end(), [](const auto& a, const auto& b)
I am trying to assign an unique value to const static unsigned int members, without having to think about assigning the right values myself (preventing human errors). I've created a minimal solution for static unsigned int members, but I would really like to use const instead, because it's faster (and neat).
This is what I came up with:
// cat.h
#define ANIMAL_INDEX 0
#define GET_ANIMAL_INDEX (ANIMAL_INDEX (ANIMAL_INDEX + 1))
class Cat
{
protected:
Cat(){}
public:
const static unsigned int lynx = GET_ANIMAL_INDEX; // 0
const static unsigned int tiger = GET_ANIMAL_INDEX; // 1
};
This is just an example, but imagine that I would have like 1000 animals or something.
Is it possible to create a macro that increments every time it is used for assignment, or do I need to create a script which generates the cat.h?
If you're happy to move the definitions of your constants outside of their class, then a simple static function based implementation solves your problem:
class UniqueIndex
{
public:
static int getNext()
{
static int theIndex = 0;
return theIndex++;
}
};
class Cat
{
protected:
Cat(){}
public:
const static unsigned int lynx;
const static unsigned int tiger;
};
const unsigned int Cat::lynx = UniqueIndex::getNext();
const unsigned int Cat::tiger = UniqueIndex::getNext();
int main()
{
std::cout << Cat::lynx << ' ' << Cat::tiger << std::endl; //output: 0 1
return 0;
}
Disregarding how questionable a design this might be, an automatic counter can be useful in many cases, so here goes...
Add an abstraction around the "index" and let that handle the counting.
Then your members can be instances of this "indexing type" instead.
Something like this:
class Index
{
public:
Index() : idx(next()) {}
Index(const Index&) = delete;
Index& operator=(const Index&) = delete;
operator int () const { return idx; }
private:
const int idx;
// Avoid the "static initialization order fiasco".
static int next() { static int i = 0; return i++;}
};
struct A
{
const static Index idx;
};
const Index A::idx;
struct B
{
const static Index idx;
const static Index idx2;
};
const Index B::idx;
const Index B::idx2;
int main()
{
cout << A::idx << " " << B::idx << " " << B::idx2 << endl;
}
So I was trying to program a target heart rate calculator in C++ and when I tried to build it, this error was returned. Just to let you know, I am instructed to separate the implementation and interface.
Here's the interface
#include <iostream>
#include <string>
class HeartRates
{
public:
// constructor initialize HeartRates
HeartRates( std::string, std::string, int, int, int );
// Setting each variable
void setFirstName( std::string );
void setLastName( std::string );
void setdobMonth( int );
void setdobDay( int );
void setdobYear( int );
void setCurrentYear( int );
std::string getFirstName() const;
std::string getLastName() const;
int getdobMonth() const;
int getdobDay() const;
int getdobYear() const;
int getCYear() const;
int getAge() const;
int getMaximumHeartRate() const;
int getTargetHeartRate() const;
private:
std::string firstName;
std::string lastName;
int dobMonth;
int dobDay;
int dobYear;
int currentYear;
};
And here's the implementation
#include <iostream>
#include <string>
#include "HeartRates.h"
using namespace std;
// constructor that initializes all the stuff
This is the line that is giving me this error: Out-of-line definition of 'HeartRates' does not match any declaration in 'HeartRates'
HeartRates::HeartRates( string first, string last, int M, int D, int Y, int cY )
{
setFirstName( first );
setLastName( last );
setdobMonth( M );
setdobDay( D );
setdobYear( Y );
setCurrentYear( cY );
}
Continue on with the code
// set functions
void HeartRates::setFirstName( string first )
{
firstName = first; // store the first name in the object
}
void HeartRates::setLastName( string last )
{
lastName = last; // store the last name in the object
}
void HeartRates::setdobMonth( int M )
{
dobMonth = M; // store the month of birth in the object
}
void HeartRates::setdobDay( int D )
{
dobDay = D; // store the day of birth in the object
}
void HeartRates::setdobYear( int Y )
{
dobYear = Y; // store the year of birth in the object
}
void HeartRates::setCurrentYear( int cY )
{
currentYear = cY;
}
// get functions
string HeartRates::getFirstName() const
{
return firstName; // return user's first name
}
string HeartRates::getLastName() const
{
return lastName; // return user's last name
}
int HeartRates::getdobMonth() const
{
return dobMonth;
}
int HeartRates::getdobDay() const
{
return dobDay;
}
int HeartRates::getdobYear() const
{
return dobYear;
}
int HeartRates::getCYear() const
{
return currentYear;
}
// Functions
int HeartRates::getAge() const
{
int age;
age = currentYear-dobYear;
return age;
}
int HeartRates::getMaximumHeartRate() const
{
int maxHeartRate;
maxHeartRate = 220 - getAge();
return maxHeartRate;
}
int HeartRates::getTargetHeartRate() const
{
int targetHeartRate;
targetHeartRate = getMaximumHeartRate() * 0.85;
return targetHeartRate;
}
Sorry for the formatting and copy and pasting everything. Newbie here, I just don't know which part of the code went wrong.
HeartRates( std::string, std::string, int, int, int );
2 strings and 3 int.
HeartRates::HeartRates( string first, string last, int M, int D, int Y, int cY )
2 strings and 4 int.
I had a similar issue today and my fix was slightly different, so I'll throw this here in case it ever helps anyone in the future. I had forward declared a class OUTSIDE of the appropriate namespace in the header, so my error looked something like this:
1. Type of 1st parameter of member declaration does not match definition
'const std::shared_ptr<MyClass> &' (aka 'const shared_ptr<MyClass> &') vs
'const std::shared_ptr<MyClass> &' (aka 'const shared_ptr<myNamespace::MyClass> &'))
The solution for me was to forward declare that class inside the namespace, rather than outside it.
Bad:
class MyClass;
namespace myNamespace {
}
Good:
namespace myNamespace {
class MyClass;
}
I'm creating a c++ program of a race.
I have the race class. Each race has a name, a distance and vector of results pointers(its a result for each participant).
The result class has a pointer to the participant and a time.
The class time has hours, minutes and seconds.
I want to sort the vector of results from the fastest time to the slowest, so to compare results I created the function bool operator <(Result& res2) const in the class result.
All the functions in the .h file are implemented, I'm just not showing them all.
I'm almost certain that the function sortResults is not right but the function operator< is giving me errors that I don't know how to solve. It gives me this error in all the if statements: Multiple markers at this line
- passing 'const Time' as 'this' argument of 'unsigned int Time::getHours()' discards qualifiers [-
fpermissive]
- Line breakpoint: race.cpp [line: 217]
- Invalid arguments ' Candidates are: unsigned int getHours() '
Can you tell me what I'm doing wrong?
.h file:
class Time
{
unsigned int hours;
unsigned int minutes;
unsigned int seconds;
public:
Time(unsigned int h, unsigned int m, unsigned int s, unsigned int ms);
Time();
unsigned int gethours();
unsigned int getMinuts();
unsigned int getSeconds();
string show();
};
class Participant {
string name;
unsigned int age;
string country;
public:
Participant(string n, unsigned int a, string c);
string getName();
string getCountry();
int getAge();
string show() const;
};
class Result {
Participant *part;
Time time;
public:
Result(Participant *p, Time t);
Participant *getParticipant() const;
Time getTime();
string show();
bool operator <(Result& res2) const;
};
class Race {
string name;
float distance;
vector<Result *> results;
public:
Race(string nm, float dist);
string getName();
void setName(string nm);
float getDistance();
vector<Result *> sortResults();
void addResult(Result *r);
string showRaceResults();
string show();
};
.cpp file:
bool Result::operator <(Result& res2) const {
if (time.gethours() < res2.getTime().gethours())
return true;
else {
if (time.gethours() > res2.getTime().gethours())
return false;
else {
if (time.getMinutes() < res2.getTime().getMinutes())
return true;
else {
if (time.getMinutes() > res2.getTime().getMinutes())
return false;
else {
if (time.getSeconds() < res2.getTime().getSeconds())
return true;
else {
return false;
}
}
}
}
}
}
vector<Result *> Race::sortResults() {
sort (results.begin(), results.end(), operator <);
return results;
}
You should declare and define Time::gethours() as constant member function.
class Time {
// ...
unsigned int gethours() const; // note the "const"
};
unsigned int Time::gethours() const { /* ... */ } // note the "const"
To sort vector<Result*>, you need to
Change Result::operator<() to take const Result& rather than Result& as parameter
Define a comparison function for Result* which looks like static bool cmpResultPtr(const Result* lhs, const Result* rhs) { return *lhs < *rhs; }
Call sort(results.begin(), results.end(), cmpResultPtr);
The function cmpResultPtr() could be defined in the .cpp file, before the definition of Race::sortResults().
You declare operator< to be const but Time::getHours, which it calls, doesn't have the same declaration. To the compiler, this means getHours could change the value of the time member which violates the constness of operator<.
Consider the following example:
struct MyStruct {
int a;
int b;
};
I can use macros to set a member from an instance of the struct by doing this:
#define setVar(x,y) instance.x = y
then in any function I can say:
setVar(a, 4)
How can I send in a as a string to the macro? Is that also possible?
setVar("a", 4)
EDIT: There are a bunch of predefined structs with members that are all of type double. I only know what struct I am using by an XML config file that is passed in. After parsing, I have a bunch of strings that are a list of all the data members and values that need to be set. I need to use this list to set values for each of the members in the struct.
It is only possible if you define the struct itself using some macro, for example:
#define MY_STRUCT_STRUCTURE FIELD(a) FIELD(b) FIELD(d) FIELD(e) FIELD(f)
struct MyStruct {
# define FIELD(name) int name;
MY_STRUCT_STRUCTURE
# undef FIELD
bool setVar(char* fieldname, int val)
{
# define FIELD(name) if(strcmp(#name,fieldname)==0){name=val; return true;};
MY_STRUCT_STRUCTURE
# undef FIELD
return false; // name not found
}
};
int main()
{
MyStruct s;
s.setVar("a",1);
s.setVar("b",2);
s.setVar("f",100);
}
I have coded some quick and dirty code, but could give you some ideas, hope that helps. The main trick here is too use unions.
struct MyStruct
{
int a;
double b;
MyStruct()
: a(0), b(0) {}
};
MyStruct instance;
union value
{
long value_a;
double value_d;
} myvalue;
void blah_a(value v)
{
instance.a = v.value_a;
}
void blah_b(value v)
{
instance.b = v.value_d;
}
struct
{
(void)(*fn)(value);
const char* key;
}
lookup_table[] =
{
{ &blah_a, "a" },
{ &blah_b, "b" }
};
void setVar(const char* c, value v)
{
for (int i = 0; lookup_table[i].fn; i++)
if (c == lookup_table[i].key)
(*(lookup_table[i].fn))(v);
}
int main(int argc, char* argv[])
{
value v;
v.value_a = 6;
setVar("a", v);
return 0;
}
Might not be what you are looking for but an alternative solution to macros etc.. would just be some encapsulation and OO design. You can change the Field class to a template later and you will be able to represent anything basically.
You can create a class
class Field
{
public:
Field(const std::string& name, const std::string& type);
virtual ~Field(void);
std::string toString() const;
std::string getName() const;
int getValue() const { return value };
private:
std::string name;
std::string type;
int value;
};
And then a structure class
#pragma once
#include <boost/ptr_container/ptr_deque.hpp>
#include <string>
class Field;
class MyStructure
{
public:
typedef boost::ptr_deque<Field> FieldList;
typedef FieldList::iterator FieldListIter;
typedef FieldList::auto_type AutoField;
MyStructure(void);
MyStructure(const std::string& name);
virtual ~MyStructure(void);
void setName(const std::string& name);
std::string getName() const;
void addField( std::auto_ptr<Field> field );
std::string getFieldValue( const std::string& name ) const;
MyStructure::AutoField removeField( const std::string& name );
std::string toString(void) const;
private:
std::string struct_name;
FieldList fields;
};
And then to use it:
auto_ptr<MySructure> struct_a(new MySructure("StructName1",0) );
struct_a->addField( auto_ptr<Field> ( new Field( "Field1", 1 ) ) );
struct_a->addField( auto_ptr<Field> ( new Field( var_str1, 2) ) );
struct_a->addField( auto_ptr<Field> ( new Field( getName(), getVal() ) ) );