Keeping track of how many times a function is called is easy when passing the counter as an argument into the function. It's also easy when returning a one from the called function. But, I do not want to go that route. The reason behind this is because it seems like bad programming (letting the function know too much information). Is there a better way to keep track of how many times this function has been called?
I'm just looking for concepts that I could study. Providing code examples is not neccessary, but might be helpful.
Edit: I'm not actually looking for profiling tools. Let me add some code to get my point across. Because scope for funcCounter ends in main, I have no way of getting back a variable from myFunction that will increment funcCounter. I could possibly return 1 from myFunction and then increment funcCounter that way, but this doesn't seem like very good programming. Is there another way to do it?
int main()
{
int funcCounter = 0;
char *mystring = "This is a silly function.";
myFunction(mystring);
cout << "Times function is called: " << funcCounter << endl;
return 0;
}
void myFunction(char *mystring)
{
cout << mystring << endl;
}
Have a static variable in your function and keep incrementing it each time the function in called.
void my_Function(void) {
static unsigned int call_count = 0;
call_count++;
}
If you want to do it for debugging reasons, then there are tools like gcov which do this for you. (I'm pretty sure Microsoft doesn't have an alternative bundled with Microsoft Visual C++)
I would do this through the use of a profiling tool like gcov (which is for linux). These programs do the work of inserting code into your program during compilation and give you a report of how many times a function is called, where its called from, and how long the program spent executing that function.
It sounds like what you are looking for is a profiler. Depending on the platform you are using there are a slew of tools available that can help you hunt down the (ab)uses of a routine.
Please revise your question with the platform for which you need profiling tools.
If the function is part of a class, you can add a static counter to the class, plus an accessor and/or reset functions:
class X
{
private:
/* diagnostics */
static int counter = 0;
int read_counter() const { return counter; }
void reset_counter() { counter = 0; }
public:
/* real code */
fcn() {
++counter;
/* ... */
}
};
The problem with adding a static counter to a standalone function is that there's no way to get at the value.
You could add a global, of course, but instead of a raw global I'd suggest an instance of a singleton containing all your diagnostic code and data.
Use a class like this one, and simply instantiate it at the top of a function (or any other block) like is done in f() below.
Note: There is some overhead for gettimeofday() so you may want to use a different timing method, but that is a completely different topic worthy of it's own question (and has been addressed before on SO).
#include <iostream>
#include <string>
#include <map>
#include <sstream>
#include <ctime>
#include <cstdlib>
#include <sys/time.h>
class PerfStats
{
private:
std::string which_;
timeval begin_;
public:
PerfStats(std::string const &file, int line)
{
std::stringstream ss;
ss << file << ':' << line;
which_ = ss.str();
gettimeofday(&begin_, NULL);
}
~PerfStats()
{
timeval end;
gettimeofday(&end, NULL);
Times[which_] = (end.tv_sec - begin_.tv_sec) + (end.tv_usec - begin_.tv_usec)/1000000.0;
++Counts[which_];
}
static std::map<std::string, double> Times;
static std::map<std::string, unsigned int> Counts;
static void Print()
{
for(std::map<std::string, double>::iterator it = Times.begin(); it != Times.end(); ++it)
std::cout << it->first << " :\t" << it->second << "s" << std::endl;
for(std::map<std::string, unsigned int>::iterator it = Counts.begin(); it != Counts.end(); ++it)
std::cout << it->first << " :\t" << it->second << " times" << std::endl;
}
};
std::map<std::string, double> PerfStats::Times;
std::map<std::string, unsigned int> PerfStats::Counts;
void f()
{
PerfStats(__FILE__, __LINE__);
usleep(1);
}
main()
{
srand(time(NULL));
for(int i = 0; i < rand(); ++i)
f();
PerfStats::Print();
}
Sample output:
test.cpp:54 : 2e-06s
test.cpp:54 : 21639 times
Bad coding style, but maybe adding global variables and if necessary mutex locks may do the trick.
Related
I've began making a program in linux with c++ and I'm trying to make it work on windows. It compiles fine, but when run I get this error: "1 [main] Trails of Cold Steel Simulator 8748 cygwin_exception::open_stackdumpfile: Dumping stack trace to Trails of Cold Steel Simulator.exe.stackdump". In the stack trace this exception occurs: "Exception: STATUS_ACCESS_VIOLATION". Here's some code;
#include "Tachi.h"
#include "AutumnLeafCutter.h"
#include <iostream>
#include "Weapon.h"
#include "Armour.h"
#include "Shoes.h"
int main() {
int stats[12] = {15,110,10,4,2,1,2,4,4,3,7,1};
Tachi* Tachi1 = new Tachi(stats, "Tachi");
Tachi1->addEquipment(new PracticeSword());
Tachi1->addEquipment(new LeatherJacket());
Tachi1->addEquipment(new WorkBoots());
Tachi1->addMasterQuartz(new Forcelvl1());
std::string input;
std::cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
while(input != "q") {
std::cout << "Your current stats are:" << std::endl;
std::cout << "\n";
std::cout << "HP EP STR DEF ATS ADF SPD DEX AGL MOV RNG" << std::endl;
for(int i = 0; i < 12; i += 1) {
std::cout << Tachi1->getBaseStats()[i] << " ";
}
std::cout << "\n\n";
std::cout << "Select a Craft by typing its name:" << std::endl;
std::cout << std::endl;
for(int i = 0; i < Tachi1->getCrafts().size(); i++) {
std::cout << Tachi1->getCrafts()[i]->getName() << std::endl;
}
std::cout << std::endl;
getline(std::cin, input);
if(Tachi1->findCraft(input) != NULL) {
Tachi1->useCraft(input);
} else {
std::cout << "You do not have this craft." << std::endl;
}
std::cout << "\n\n\n";
}
}
Im extremely sorry for any formatting, I've never posted here. The error comes from lines 14,15,16 and 18. When I replaced all the "new xxx()" with NULL and comment out the body of the function with them, the program works. It does this for both addEquipment() and addMasterQuartz(). This is the functions;
void Character::addEquipment(Equipment* e) {
equipment.push_back(e);
std::cin.get();
for(int i = 0; i < 12; i++) {
baseStats[i] += equipment[equipment.size()]->getStatsModifier()[i];
}
}
and
void Character::addMasterQuartz(MasterQuartz* mq) {
masterQuartz = mq;
for(int i = 0; i < 12; i++) {
baseStats[i] += masterQuartz->getStatsModifier()[i];
}
}
Im guessing its a problem with the baseStats[i] += xxx stuff as its the only thing that occurs in both, but I have no idea how to fix that. It could also occur when the stuff is made using new xxx().
I can provide whatever else is needed. Thanks!!!!
EDIT:
I kept testing and the problem seems to lie in the creating of the objects. It worked on linux. Here is one of the object codes, they are all similiar and all crash the program;
#include "Armour.h"
Armour::Armour(int* sm, std::string n):Equipment(sm, n) {}
LeatherJacket::LeatherJacket():Armour(stats, armourName) {}
with header file;
#ifndef ARMOUR_H
#define ARMOUR_H
#include "Equipment.h"
class Armour:public Equipment {
public:
Armour(int* sm, std::string n);
};
class LeatherJacket:public Armour {
int stats[12] = {0,0,0,5,0,0,0,0,0,0,0,0};
std::string armourName = "Leather Jacket";
public:
LeatherJacket();
};
#endif
As soon as I remembered I did this I tried compiling (I think) with -std=c++11, it didnt help.
This is your error
baseStats[i] += equipment[equipment.size()]->getStatsModifier()[i];
By definition this is an out of bounds access on your vector, if a vector has a certain size, then the valid indexes are 0 to size - 1, not 0 to size.
It's fairly obvious that you wanted to access the last item in the vector. You can do that like this
baseStats[i] += equipment[equipment.size() - 1]->getStatsModifier()[i];
but even clearer is to use the back method.
baseStats[i] += equipment.back()->getStatsModifier()[i];
Another way would be to use the e variable you've just pushed onto the vector.
baseStats[i] += e->getStatsModifier()[i];
Adding some detail to the problem spotted by Useless, this code is incorrect.
class LeatherJacket : public Armour {
int stats[12] = {0,0,0,5,0,0,0,0,0,0,0,0};
std::string armourName = "Leather Jacket";
public:
LeatherJacket();
};
LeatherJacket::LeatherJacket() : Armour(stats, armourName) {}
The problem is the order in which things happen. First the Armour constructor is called, then the stats and armourName variables are initialised. So the call to the Armour constructor is using uninitiialised variables and will likely crash.
Several solutions possible, the best is probably to use virtual functions.
Making a couple of assumptions about Equipment (which isn't specified the question) it seems you should do something like this.
// header file
class Equipment
{
public:
virtual ~Equipment() {}
virtual std::string getName() const = 0;
virtual const int* getStatsModifier() const = 0;
};
class Armour : public Equipment
{
};
class LeatherJacket : public Armour
{
static const int stats[12];
public:
virtual std::string getName() const { return "Leather Jacket"; }
virtual const int* getStatsModifier() const { return stats; }
};
// source file
const int LeatherJacket::stats[12] = {0,0,0,5,0,0,0,0,0,0,0,0};
This answer adds pure virtual functions to the base class Equipment (which has become an interface), and implements those functions in LeatherJacket. Because the functions are virtual the appropriate function will always be called and there no need to pass the information down to Equipment. Also since it seems to be per-class constant data, stats has been made static const. Until you get to C++17 static const arrays must be defined in a source file, not the header file, as shown above.
Firstly, I'm going to replace the int[12] arrays with a proper type. Partly so the magic number 12 isn't littered all over the code and hard to change later, and partly because it will behave better (ie, not decay to a pointer in some contexts). This needs C++11.
#include <array>
using Stats = std::array<int, 12>;
To me it looks like Armour should have stats and a name, initialized from the arguments passed to its constructor (which you currently ignore).
Like so:
class Armour: public Equipment {
public:
Stats m_stats;
std::string m_name;
Armour(Stats const& s, std::string const &n) : m_stats(s), m_name(n) {}
};
You were already passing those two arguments to the constructor - you just weren't doing anything with them. Now you are.
This means that when we later have leather, scale, chain and plate subclasses, I can have a pointer of type Armour* and not need to worry about which subclass I'm looking at: the stats are available right there in the base class.
I made the members public, which is generally bad style, to save space. It might not matter for your use. I named the members with the m_ prefix so they can't accidentally get confused with similarly-named non-members. It's broadly good style but not essential.
LeatherArmour doesn't need an additional copy per instance, it just needs one of each for the whole class - so they should be const static members.
class LeatherJacket: public Armour {
static const Stats stats {0,0,0,5,0,0,0,0,0,0,0,0};
static const std::string name{"Leather Jacket"};
public:
LeatherJacket() : Armour(stats, name) {}
};
I made the LeatherJacket-specific stat values static const by writing static const in front of them.
The static means that every LeatherJacket has the same base stats, so you don't need a copy per instance, just one copy for the whole class. It's const because the base stats for leather jackets never change over time. You still have the base class member Armour::m_stats which can change as your individual leather jacket gets damaged, repaired, buffed or whatever.
Again, the LeatherJacket constructor was already passing (the equivalent of) these members to the base class constructor, but now they already exist (see the link above about static storage duration). The original instance variables didn't exist when you used them, because the derived (LeatherJacket) object and its data members aren't really constructed until after the base class subobject.
I have a Storage class that keeps a list of Things:
#include <iostream>
#include <list>
#include <functional>
class Thing {
private:
int id;
int value = 0;
static int nextId;
public:
Thing() { this->id = Thing::nextId++; };
int getId() const { return this->id; };
int getValue() const { return this->value; };
void add(int n) { this->value += n; };
};
int Thing::nextId = 1;
class Storage {
private:
std::list<std::reference_wrapper<Thing>> list;
public:
void add(Thing& thing) {
this->list.push_back(thing);
}
Thing& findById(int id) const {
for (std::list<std::reference_wrapper<Thing>>::const_iterator it = this->list.begin(); it != this->list.end(); ++it) {
if (it->get().getId() == id) return *it;
}
std::cout << "Not found!!\n";
exit(1);
}
};
I started with a simple std::list<Thing>, but then everything is copied around on insertion and retrieval, and I didn't want this because if I get a copy, altering it does not reflect on the original objects anymore. When looking for a solution to that, I found about std::reference_wrapper on this SO question, but now I have another problem.
Now to the code that uses them:
void temp(Storage& storage) {
storage.findById(2).add(1);
Thing t4; t4.add(50);
storage.add(t4);
std::cout << storage.findById(4).getValue() << "\n";
}
void run() {
Thing t1; t1.add(10);
Thing t2; t2.add(100);
Thing t3; t3.add(1000);
Storage storage;
storage.add(t3);
storage.add(t1);
storage.add(t2);
temp(storage);
t2.add(10000);
std::cout << storage.findById(2).getValue() << "\n";
std::cout << storage.findById(4).getValue() << "\n";
}
My main() simply calls run(). The output I get is:
50
10101
Not found!!
Although I was looking for:
50
10101
50
Question
Looks like the locally declared object t4 ceases to exist when the function returns, which makes sense. I could prevent this by dynamically allocating it, using new, but then I didn't want to manage memory manually...
How can I fix the code without removing the temp() function and without having to manage memory manually?
If I just use a std::list<Thing> as some suggested, surely the problem with t4 and temp will cease to exist, but another problem will arise: the code won't print 10101 anymore, for example. If I keep copying stuff around, I won't be able to alter the state of a stored object.
Who is the owner of the Thing in the Storage?
Your actual problem is ownership. Currently, your Storage does not really contain the Things but instead it is left to the user of the Storage to manage the lifetime of the objects you put inside it. This is very much against the philosophy of std containers. All standard C++ containers own the objects you put in them and the container manages their lifetime (eg you simply call v.resize(v.size()-2) on a vector and the last two elements get destroyed).
Why references?
You already found a way to make the container not own the actual objects (by using a reference_wrapper), but there is no reason to do so. Of a class called Storage I would expect it to hold objects not just references. Moreover, this opens the door to lots of nasty problems, including undefined behaviour. For example here:
void temp(Storage& storage) {
storage.findById(2).add(1);
Thing t4; t4.add(50);
storage.add(t4);
std::cout << storage.findById(4).getValue() << "\n";
}
you store a reference to t4 in the storage. The thing is: t4s lifetime is only till the end of that function and you end up with a dangling reference. You can store such a reference, but it isnt that usefull because you are basically not allowed to do anything with it.
Aren't references a cool thing?
Currently you can push t1, modify it, and then observe that changes on the thingy in Storage, this might be fine if you want to mimic Java, but in c++ we are used to containers making a copy when you push something (there are also methods to create the elements in place, in case you worry about some useless temporaries). And yes, of course, if you really want you can make a standard container also hold references, but lets make a small detour...
Who collects all that garbage?
Maybe it helps to consider that Java is garbage-collected while C++ has destructors. In Java you are used to references floating around till the garbage collector kicks in. In C++ you have to be super aware of the lifetime of your objects. This may sound bad, but acutally it turns out to be extremely usefull to have full control over the lifetime of objects.
Garbage? What garbage?
In modern C++ you shouldnt worry to forget a delete, but rather appreciate the advantages of having RAII. Acquiring resources on initialzation and knowing when a destructor gets called allows to get automatic resource management for basically any kind of resource, something a garbage collector can only dream of (think of files, database connections, etc.).
"How can I fix the code without removing the temp() function and without having to manage memory manually?"
A trick that helped me a lot is this: Whenever I find myself thinking I need to manage a resource manually I stop and ask "Can't someone else do the dirty stuff?". It is really extremely rare that I cannot find a standard container that does exactly what I need out of the box. In your case, just let the std::list do the "dirty" work.
Can't be C++ if there is no template, right?
I would actually suggest you to make Storage a template, along the line of:
template <typename T>
class Storage {
private:
std::list<T> list;
//....
Then
Storage<Thing> thing_storage;
Storage<int> int_storage;
are Storages containing Things and ints, respectively. In that way, if you ever feel like exprimenting with references or pointers you could still instantiate a Storage<reference_wrapper<int>>.
Did I miss something?...maybe references?
I won't be able to alter the state of a stored object
Given that the container owns the object you would rather let the user take a reference to the object in the container. For example with a vector that would be
auto t = std::vector<int>(10,0); // 10 element initialized to 0
auto& first_element = t[0]; // reference to first element
first_element = 5; // first_element is an alias for t[0]
std::cout << t[0]; // i dont want to spoil the fun part
To make this work with your Storage you just have to make findById return a reference. As a demo:
struct foo {
private:
int data;
public:
int& get_ref() { return data;}
const int& get_ref() const { return data;}
};
auto x = foo();
x.get_ref = 12;
TL;DR
How to avoid manual resource managment? Let someone else do it for you and call it automatic resource management :P
t4 is a temporary object that is destroyed at exit from temp() and what you store in storage becomes a dangling reference, causing UB.
It is not quite clear what you're trying to achieve, but if you want to keep the Storage class the same as it is, you should make sure that all the references stored into it are at least as long-lived as the storage itself. This you have discovered is one of the reasons STL containers keep their private copies of elements (others, probably less important, being—elimination of an extra indirection and a much better locality in some cases).
P.S. And please, can you stop writing those this-> and learn about initialization lists in constructors? >_<
In terms of what your code actually appears to be doing, you've definitely overcomplicated your code, by my estimation. Consider this code, which does all the same things your code does, but with far less boilerplate code and in a way that's far more safe for your uses:
#include<map>
#include<iostream>
int main() {
std::map<int, int> things;
int & t1 = things[1];
int & t2 = things[2];
int & t3 = things[3];
t1 = 10;
t2 = 100;
t3 = 1000;
t2++;
things[4] = 50;
std::cout << things.at(4) << std::endl;
t2 += 10000;
std::cout << things.at(2) << std::endl;
std::cout << things.at(4) << std::endl;
things.at(2) -= 75;
std::cout << things.at(2) << std::endl;
std::cout << t2 << std::endl;
}
//Output:
50
10101
50
10026
10026
Note that a few interesting things are happening here:
Because t2 is a reference, and insertion into the map doesn't invalidate references, t2 can be modified, and those modifications will be reflected in the map itself, and vise-versa.
things owns all the values that were inserted into it, and it will be cleaned up due to RAII, and the built-in behavior of std::map, and the broader C++ design principles it is obeying. There's no worry about objects not being cleaned up.
If you need to preserve the behavior where the id incrementing is handled automatically, independently from the end-programmer, we could consider this code instead:
#include<map>
#include<iostream>
int & insert(std::map<int, int> & things, int value) {
static int id = 1;
int & ret = things[id++] = value;
return ret;
}
int main() {
std::map<int, int> things;
int & t1 = insert(things, 10);
int & t2 = insert(things, 100);
int & t3 = insert(things, 1000);
t2++;
insert(things, 50);
std::cout << things.at(4) << std::endl;
t2 += 10000;
std::cout << things.at(2) << std::endl;
std::cout << things.at(4) << std::endl;
things.at(2) -= 75;
std::cout << things.at(2) << std::endl;
std::cout << t2 << std::endl;
}
//Output:
50
10101
50
10026
10026
These code snippets should give you a decent sense of how the language works, and what principles, possibly unfamiliar in the code I've written, that you need to learn about. My general recommendation is to find a good C++ resource for learning the basics of the language, and learn from that. Some good resources can be found here.
One last thing: if the use of Thing is critical to your code, because you need more data saved in the map, consider this instead:
#include<map>
#include<iostream>
#include<string>
//Only difference between struct and class is struct sets everything public by default
struct Thing {
int value;
double rate;
std::string name;
Thing() : Thing(0,0,"") {}
Thing(int value, double rate, std::string name) : value(value), rate(rate), name(std::move(name)) {}
};
int main() {
std::map<int, Thing> things;
Thing & t1 = things[1];
t1.value = 10;
t1.rate = 5.7;
t1.name = "First Object";
Thing & t2 = things[2];
t2.value = 15;
t2.rate = 17.99999;
t2.name = "Second Object";
t2.value++;
std::cout << things.at(2).value << std::endl;
t1.rate *= things.at(2).rate;
std::cout << things.at(1).rate << std::endl;
std::cout << t1.name << "," << things.at(2).name << std::endl;
things.at(1).rate -= 17;
std::cout << t1.rate << std::endl;
}
Based on what François Andrieux and Eljay have said (and what I would have said, had I got there first), here is the way I would do it, if you want to mutate objects you have already added to a list. All that reference_wrapper stuff is just a fancy way of passing pointers around. It will end in tears.
OK. here's the code (now edited as per OP's request):
#include <iostream>
#include <list>
#include <memory>
class Thing {
private:
int id;
int value = 0;
static int nextId;
public:
Thing() { this->id = Thing::nextId++; };
int getId() const { return this->id; };
int getValue() const { return this->value; };
void add(int n) { this->value += n; };
};
int Thing::nextId = 1;
class Storage {
private:
std::list<std::shared_ptr<Thing>> list;
public:
void add(const std::shared_ptr<Thing>& thing) {
this->list.push_back(thing);
}
std::shared_ptr<Thing> findById(int id) const {
for (std::list<std::shared_ptr<Thing>>::const_iterator it = this->list.begin(); it != this->list.end(); ++it) {
if (it->get()->getId() == id) return *it;
}
std::cout << "Not found!!\n";
exit(1);
}
};
void add_another(Storage& storage) {
storage.findById(2)->add(1);
std::shared_ptr<Thing> t4 = std::make_shared<Thing> (); t4->add(50);
storage.add(t4);
std::cout << storage.findById(4)->getValue() << "\n";
}
int main() {
std::shared_ptr<Thing> t1 = std::make_shared<Thing> (); t1->add(10);
std::shared_ptr<Thing> t2 = std::make_shared<Thing> (); t2->add(100);
std::shared_ptr<Thing> t3 = std::make_shared<Thing> (); t3->add(1000);
Storage storage;
storage.add(t3);
storage.add(t1);
storage.add(t2);
add_another(storage);
t2->add(10000);
std::cout << storage.findById(2)->getValue() << "\n";
std::cout << storage.findById(4)->getValue() << "\n";
return 0;
}
Output is now:
50
10101
50
as desired. Run it on Wandbox.
Note that what you are doing here, in effect, is reference counting your Things. The Things themselves are never copied and will go away when the last shared_ptr goes out of scope. Only the shared_ptrs are copied, and they are designed to be copied because that's their job. Doing things this way is almost as efficient as passing references (or wrapped references) around and far safer. When starting out, it's easy to forget that a reference is just a pointer in disguise.
Given that your Storage class does not own the Thing objects, and every Thing object is uniquely counted, why not just store Thing* in the list?
class Storage {
private:
std::list<Thing*> list;
public:
void add(Thing& thing) {
this->list.push_back(&thing);
}
Thing* findById(int id) const {
for (auto thing : this->list) {
if (thing->getId() == id) return thing;
}
std::cout << "Not found!!\n";
return nullptr;
}
};
EDIT: Note that Storage::findById now returns Thing* which allows it to fail gracefully by returning nullptr (rather than exit(1)).
I'm an absolute newbee when it comes to programming and I'm trying to teach myself the basics by just solving some easy "problems" in C++.
I have searched the web for an exact answer to my question before posting it here and haven't found one so far, however that may be because of (1).
So, what I'm looking for is a way to declare a class member that gets automatically calculated from other members of the same class, so that the calculated class member can be used just like an explicitly defined class member would. For example imagine a struct called creature that has the properties/members creature.numberofhands, creature.fingersperhand and finally the property creature.totalfingers that automatically gets calculated from the above members.
Heres an example of the closest I got to what I wanted to achieve:
#include <iostream>
typedef struct creature {
int numberofhands;
int fingersperhand;
int totalfingers();
} creature;
int creature::totalfingers()
{
return numberofhands * fingersperhand;
};
int main()
{
creature human;
human.numberofhands = 2;
human.fingersperhand = 5;
printf("%d",human.totalfingers());
return(0);
}
What's really annoying me about this, is that I have to treat the calculated one DIFFERENTLY from the explicitly defined ones, i.e. I have to put "()" after it.
How can I change the code, so I can use: human.totalfingers without ever explicitly defining it?
The simplest option would be to use public member functions and make the actual properties hidden.
Something like this:
class Creature {
public:
Creature(int numhands, int fingersperhand) // constructor
: m_numhands{numhands}, m_fingersperhand{fingersperhand}
{ }
int fingersPerHand() const { return m_fingersperhand; }
int numberOfHands() const { return m_numhands; }
int totalFingers() const { return numberOfHands() * fingersPerHand(); }
private:
const int m_numhands;
const int m_fingersperhand;
};
The private member variables are an implementation detail. Users of the class just use the three public member functions to get the different number of fingers after construction and don't need to care that two of them are returning constant stored numbers and the third returns a calculated value - that's irrelevant to users.
An example of use:
#include <iostream>
int main()
{
Creature human{2, 5};
std::cout << "A human has "
<< human.totalFingers() << " fingers. "
<< human.fingersPerHand() << " on each of their "
<< human.numberOfHands() << " hands.\n";
return 0;
}
If - as per your comment - you don't want to use a constructor (although that's the safest way to ensure you don't forget to initialize a member), you can modify the class like this:
class CreatureV2 {
public:
int fingersPerHand() const { return m_fingersperhand; }
int numberOfHands() const { return m_numhands; }
int totalFingers() const { return numberOfHands() * fingersPerHand(); }
void setFingersPerHand(int num) { m_fingersperhand = num; }
void setNumberOfHands(int num) { m_numhands = num; }
private:
// Note: these are no longer `const` and I've given them default
// values matching a human, so if you do nothing you'll get
// human hands.
int m_numhands = 2;
int m_fingersperhand = 5;
};
Example of use of the modified class:
#include <iostream>
int main()
{
CreatureV2 human;
std::cout << "A human has "
<< human.totalFingers() << " fingers. "
<< human.fingersPerHand() << " on each of their "
<< human.numberOfHands() << " hands.\n";
CreatureV2 monster;
monster.setFingersPerHand(7);
monster.setNumberOfHands(5);
std::cout << "A monster has "
<< monster.totalFingers() << " fingers. "
<< monster.fingersPerHand() << " on each of their "
<< monster.numberOfHands() << " hands.\n";
CreatureV2 freak;
freak.setFingersPerHand(9);
// Note: I forgot to specify the number of hands, so a freak get
// the default 2.
std::cout << "A freak has "
<< freak.totalFingers() << " fingers. "
<< freak.fingersPerHand() << " on each of their "
<< freak.numberOfHands() << " hands.\n";
return 0;
}
Note: all of the above assumes you are using a modern C++14 compiler.
What you have described is one of the reasons why encapsulation and "member variables should be private" is the recommended way of doing things in C++.
If every variable is accessed through a function, then everything is consistent, and refactoring from a member variable to a computation is possible.
Some languages, like C# or D, have the concept of "properties", which provide a way around the issue, but C++ does not have such a construct.
For fun, the proxy way to avoid extra parenthesis, (but with some extra costs):
class RefMul
{
public:
RefMul(int& a, int& b) : a(a), b(b) {}
operator int() const { return a * b; }
private:
int& a;
int& b;
};
struct creature {
int numberofhands;
int fingersperhand;
RefMul totalfingers{numberofhands, fingersperhand};
};
Demo
Note: to use RefMul with printf, you have to cast to int:
printf("%d", int(human.totalfingers));
That cast would not be required if you use c++ way to print:
std::cout << human.totalfingers;
If you're after consistency, you can make your changes the other way around. Replace the two member variables with constant methods which simply return copies of the member variables. That way, the way you access data is consistent and you don't have to worry about some code changing the values of the member variables when it shouldn't.
Others have provided very good answers. If you are looking for consistency, probably the easiest way is to make use of member functions (as #Jesper Juhl has answered).
On the other hand, if you strictly want to use class members that are calculated automatically from other members, you can use properties. Properties (as are defined in C# and Groovy) are not a standard feature of C++ but there are ways to implement them in C++. This SO question has a very good overview of the ways that properties can be defined and used in C++. My favorite way of defining properties is taking advantage of Microsoft-specific extension for properties in Visual C++ (obviously, this approach is specific to Microsoft Visual C++). A documentation of properties in Visual C++ can be found in MSDN. Using properties in Visual C++, your code can be modified to:
struct creature {
int numberofhands; // use of public member variables are generally discouraged
int fingersperhand;
__declspec(property(get = get_totalfingers)) // Microsoft-specific
int totalfingers;
private:
int fingers;
int get_totalfingers()
{
return numberofhands * fingersperhand; // This is where the automatic calculation takes place.
}
};
This class can be used like this:
#include <iostream>
int main()
{
creature martian;
martian.numberofhands = 2;
martian.fingersperhand = 4; // Marvin the Martian had 4!
// This line will print 8
std::cout << "Total fingers: " << martian.totalfingers << std::endl;
return 0;
}
As I said earlier, properties are not a standard feature of C++ but there are ways to get them in C++ which either rely on smart tricks or using compiler-specific features. IMHO, using simple functions (as #Jesper Juhl described) is a better alternative.
So right now I'm trying to implement a list using STL but I'm stuck at what to do for the print function. I've searched for solutions but I'm having a difficult time understanding. I'm having some trouble using iterators in this implementation as well.
Here's my code:
AnyList.h:
class AnyList
{
public:
AnyList();
int getNumOfElem() const;
void insertFront(int data);
void forwardPrint();
private:
list<int> *ptr;
};
AnyList.cpp:
AnyList::AnyList()
{
ptr->begin(); //added
}
int AnyList::getNumOfElem() const
{
return static_cast<int>(ptr->size());
}
void AnyList::insertFront(int data)
{
ptr->push_front(data);
}
void AnyList::forwardPrint()
{
//const list<int> & iter; //removed
list<int>::const_iterator i;
for (i = ptr->begin(); i != ptr->end(); ++i) //changed
{
cout << *i << " ";
cout << endl;
}
}
Main.cpp
int main()
{
AnyList list1, list2;
list1.insertFront(10);
list1.insertFront(11);
list1.insertFront(12);
list1.insertFront(13);
list1.insertFront(14);
cout << "\nList 1: ";
list1.forwardPrint();
}
Any insight would be greatly appreciated. As of now I don't even know how to test whether or not the insertFront function works without the print function.
Edit: made some changes to code and marked them.
Edit2: Just going to include the screenshot of the instructions so there'd be less confusion as to what I'm supposed to be accomplishing here.
Just to reiterate - The project file came with the AnyList class, which includes the private member variable list *ptr and the function getNumOfElements() as an example of a working function. There's a lot more to the main file but I just included the first part that should work if I implement the insertFront and forwardPrint functions correctly.
Edit 3: To further clarify what I believe I am confused about, the examples I see everywhere go something like this:
vector<string> SS;
SS.push_back("The number is 10");
SS.push_back("The number is 20");
SS.push_back("The number is 30");
cout << "Loop by index:" << endl;
int ii;
for(ii=0; ii < SS.size(); ii++)
{
cout << SS[ii] << endl;
}
cout << endl << "Constant Iterator:" << endl;
Which is nice but how do I implement something like this as what the instructions say that I should be doing? What I tried didn't work.
In the forwardPrint function you have this:
const list<int> & iter;
That defines a variable iter that is not an iterator (no matter the name) but a reference to a list. That is wrong in two ways: First you define a variable that has no connection to your actual list. Second you define the variable to be a reference to a list, but without making it actually reference anything.
You should use your member variable as the list instead. So something like
for (i = ptr->begin(); i != ptr->end(); ++i) { ... }
On a slightly related note, why do you have a pointer to a list? A pointer which you don't even initialize? That means if and when you get the program to build you will have undefined behavior as you dereference the uninitialized pointer, which doesn't point anywhere valid.
Don't use a pointer. Use an actual instance instead.
Or, as a couple of comments noted, why wrap the std::list class at all?
I am trying to use the function signal(int,void(*)(int)) from <csignal> to handle the floating point exception SIGFPE. I'd like to be able to print some useful diagnostics besides just a message saying "Floating point exception" or something to that effect. This means the function I pass as the handler to signal needs access to some of the data in my code. Therein lies the rub.
The function must return void and accept only 1 parameter of type int. I cannot make the handler a member function of my data storage class since then the type would be void(Foo::*)(int) due to the hidden this pointer.
I thought about using lambdas to try and make an anonymous function like this;
void handler(int nSig, Foo data)
{
// do something
}
// snip
Foo data;
signal(SIGFPE, [&](int nSig)->void{handler(nSig,data);});
however because the lambda captures the variable data from outside the compiler will not let it be cast to a pointer to void(*)(int) (which is a shame as this seems like an ideal use for lambdas).
I could simply make data a global variable which could then be seen in handler but I am loath to do this for obvious reasons.
So my question is thus; what is the best way of mimicking anonymous functions in C++?
Note: I would prefer a native C++ solution and not to have to use boost or equivalent.
This is indeed a good question. Let's figure out what is going before blaming C++ though. Just think about how lambdas are implemented.
The most simple lambda is when no data is captured. If that is the case, its underlying type becomes a simple plain function. For example, a lambda like this:
[] (int p0) {}
will be an equivalent of a simple function:
void foo(int p0)
{
}
That actually perfectly works in case you want that lambda to become a function pointer. For example:
#include <string>
#include <csignal>
#include <iostream>
int main()
{
int ret;
signal(SIGINT, [](int signal) {
std::cout << "Got signal " << signal << std::endl;
});
std::cin >> ret;
return ret;
}
So far so good. But now you want to associate some data with your signal handler (by the way, the code above is undefined behavior as you can only execute signal-safe code inside a signal handler). So you want a lambda like:
#include <string>
#include <csignal>
#include <iostream>
struct handler_context {
std::string code;
std::string desc;
};
int main()
{
int ret;
handler_context ctx({ "SIGINT", "Interrupt" });
signal(SIGINT, [&](int signal) {
std::cout << "Got signal " << signal
<< " (" << ctx.code << ": " << ctx.desc
<< ")\n" << std::flush;
});
std::cin >> ret;
return ret;
}
Let's forget for a moment about a syntactic sugar of C++ lambdas. It is no secret that you can "mimic" lambda even in C or assembler. So how would that look, actually? "Lambda" in C-style could look like this (this is still C++):
#include <string>
#include <cstdlib>
#include <iostream>
/*
* This is a context associated with our lambda function.
* Some dummy variables, for the sake of example.
*/
struct lambda_captures {
int v0;
int v1;
};
static int lambda_func(int p0, void *ctx) // <-- This is our lambda "function".
{
lambda_captures *captures = (lambda_captures *)ctx;
std::cout << "Got " << p0 << " (ctx: "
<< captures->v0 << ", " << captures->v1
<< ")\n" << std::flush;
return 0;
}
// Below is an example of API function provided to the user that can
// invoke a callback supplied by the user.
static void some_api_function(int (*callback)(int p, void *data), void *data)
{
callback(12345, data);
callback(98765, data);
}
int main()
{
lambda_captures captures;
captures.v0 = 1986;
captures.v1 = 2012;
some_api_function(lambda_func, (void *)&captures);
return EXIT_SUCCESS;
}
Above is a C style, C++ tends to pass "context" as "this", which is always an implicit first argument. If our API supported passing "data" as first argument, we could apply pointer to member conversion (PMF) and write something like this:
#include <string>
#include <cstdlib>
#include <iostream>
struct some_class {
int v0;
int v1;
int func(int p0)
{
std::cout << "Got " << p0 << " (ctx: "
<< v0 << ", " << v1
<< ")\n" << std::flush;
return p0;
}
};
static void some_api_function(int (*callback)(void *data, int p), void *data)
{
callback(data, 12345);
callback(data, 98765);
}
int main()
{
typedef int (*mpf_type)(void *, int);
some_class clazz({ 1986, 2012 }); // <- Note a bit of a Java style :-)
some_api_function((mpf_type)&some_class::func, (void *)&clazz);
return EXIT_SUCCESS;
}
In the above two examples, note that "data" is always passed around. This is very important. If the API that is supposed to invoke your callback does not accept a "void *" pointer that is passed back to your callback somehow, there is no way you can associate any context with the callback. The only exception is global data. For example, this API is bad:
#include <string>
#include <cstdlib>
#include <iostream>
struct lambda_captures {
int v0;
int v1;
};
static int lambda_func(int p0)
{
/*
// WHERE DO WE GET OUR "lambda_captures" OBJECT FROM????
lambda_captures *captures = (lambda_captures *)ctx;
std::cout << "Got " << p0 << " (ctx: "
<< captures->v0 << ", " << captures->v1
<< ")\n" << std::flush;
*/
return 0;
}
// Below is an example of API function provided to the user that can
// invoke a callback supplied by the user.
static void some_api_function(int (*callback)(int p))
{
callback(12345);
callback(98765);
}
int main()
{
lambda_captures captures;
captures.v0 = 1986;
captures.v1 = 2012;
some_api_function(lambda_func /* How do we pass a context??? */);
return EXIT_SUCCESS;
}
That being said, an old signal API is exactly like that. The only way to work around the problem is to actually put your "context" into a global scope. Then signal handler function can access it because the address is well known, for example:
#include <string>
#include <cstdlib>
#include <iostream>
struct lambda_captures {
int v0;
int v1;
};
lambda_captures captures({ 1986, 2012 }); // Whoa-la!!!
static int lambda_func(int p0)
{
std::cout << "Got " << p0 << " (ctx: "
<< captures.v0 << ", " << captures.v1
<< ")\n" << std::flush;
return 0;
}
// Below is an example of API function provided to the user that can
// invoke a callback supplied by the user.
static void some_api_function(int (*callback)(int p))
{
callback(12345);
callback(98765);
}
int main()
{
some_api_function(lambda_func);
return EXIT_SUCCESS;
}
This is what people have to deal with. Not only in case with signals API. This applies to other things as well. For example, interrupt handler processing. But that low-level programming where you have to deal with hardware. Of course, providing this sort of API in the user-space was not the best idea. And I will mention it again - there is only a small set of things you can do in a signal handler. You can only call async-signal-safe functions.
Of course, old API is not going away anytime soon because it is actually a POSIX standard. However, developers recognize the problem and there are better ways to handle signals. In Linux, for example, you can use eventfd to install a signal handler, associate it with arbitrary context and do whatever you want in the callback function.
At any rate, let's get back to the lambda you were playing with. The problem is not with C++, but with signals API that leaves no way for you to pass a context except using a global variable. That being said, it works with lambdas too:
#include <string>
#include <cstdlib>
#include <csignal>
#include <iostream>
struct some_data {
std::string code;
std::string desc;
};
static some_data data({ "SIGING", "Interrupt" });
int main()
{
signal(SIGINT, [](int signal) {
std::cout << "Got " << signal << " (" << data.code << ", "
<< data.desc << ")\n" << std::flush;
});
return EXIT_SUCCESS;
}
Therefore, there is no shame in what C++ is doing here as it does a right thing.
There is no such thing as an anonymous function in C (C++ is irrelevant here, as the function must abide by the C calling convention).
The only thing you can do is shiver access globals from the handler, probably global variables (and not constants which would be fine).
I advise making those globals thread local to avoid multithreading issues, but it is still bad in the sense that global variables make for more brittle applications.
How to ?
Note: as Luc Danton patiently explained to me, a signal may interrupt any non-atomic activity, and thus reading from a global is safe only if it is a lock-free atomic (or a few other things). Unfortunately std::function may not be so, depending on your implementation, I will still leave this code to explain how it could be done providing that std::function accesses are atomic.
It is possible to create a trampoline that will call stateful stuff, isolating thread and allowing re-entrant calls.
typedef std::function<void(int)> SignalHandlerType;
extern thread_local ignalHandlerType SignalHandler;
And we create the following accessor (passed to signal):
void handle_signal(int const i) {
if (SignalHandler) { SignalHandler(i); }
}
as well as the following RAII setter:
class SignalSetter: boost::noncopyable {
public:
SignalSetter(int signal, SignalHandlerType&& sh):
signal(signal), chandler(0), handler(sh)
{
chandler = std::signal(signal, &handle_signal<T>);
swap(SignalHandler, handler);
}
~SignalSetter() {
std::signal(signal, chandler);
swap(SignalHandler, handler);
}
private:
typedef void(*CHandlerType)(int);
int signal;
CHandlerType chandler;
SignalHandlerType handler;
};
Note: both the global variable and the handle_signal could be private to the SignalSetter class... but since std::signal is not...
Expected usage:
int main(int argc, char* argv[]) {
SignalSetter setter(SIGFPE, [argc, argv]() {
std::cout << argc << ": " << argc << std::endl;
});
// do what you want.
}
You cannot easily create a new static function in runtime, some JIT compilers libs are able to do this.
If you need only a reasonable number of pointers, you can create some pool of static functions by specializing a template.
So easiest way is to wrap C++ Functors by a static function. The problem here is that there is no something like user data parameter. There is only one parameter, that is a number of signal. Since there are only 64 signals, you can create a static array of std::function< void(int) > and call each depending on signal number. Some simple example:
typedef std::function< void(int) > SignalFunc;
static std::array< SignalFunc, 64 > signalsFunc;
static void cHandler(int nSig)
{
signalsFunc.at(nSig)(nSig);
}
SignalFunc RegisterSystemSignal( int sig, SignalFunc func )
{
if( signal( sig, func ? &cHandler : (sighandler_t)SIG_DFL ) != SIG_ERR )
{
func.swap( signalsFunc.at( sig ) );
return func;
}
throw some_error();
}
So now you can do that:
RegisterSystemSignal(SIGFPE, [&](int nSig)->void{handler(nSig,data);});
There is also a sigaction witch have more features.