#include <queue>
#include <vector>
#include <string>
usingnamespace std;
class cSoundIF
{
string _message;
float _freq;
public:
cSoundIF(string message, float freq) : _message(message), _freq(freq) {}
};
class cStations
{
public:
cStations() {}
void step(queue<cSoundIF> &lSoundBuf) //passing by reference here
{
lSoundBuf.push(cSoundIF("Hello",107.1f)); // Hard coded for this post
}
};
void PlaySounds(queue<cSoundIF> &lSoundBuf) //passing by reference here
{
while (!lSoundBuf.empty())
{
//Playing the sounds, then:
lSoundBuf.pop();
}
}
int main()
{
vector<cStations> vStation;
while(true)
{
queue<cSoundIF> qSoundBuf;
if (rand()%250) vStation.push_back(cStations()); //Add a station at random
for (vector<cStations>::iterator it = vStation.begin(); it < vStation.end(); it++)
it->step(qSoundBuf); //Add messages for each station, passing by reference
if (rand()%250 && !vStation.empty()) vStation.pop_back(); //Delete a station
PlaySounds(qSoundBuf); //Play the messages, passing by reference
}
return 0;
}
How about if I want to pass it into the windows "CreateThread()" function? To do this, I need to send a void pointer. The recipient wouldn't know the size of the object so I'm not sure if the resulting STL container in the function would understand how to construct itself.
You can pass anything by const reference(const&) and only non const lvalue(not a temporary object) by reference. It doesn't depend on the type.
In fact, you should pass anything except buitlin types(like int, float, ...) and very small types like functors by constant refrerence if the function doesn't modify the parameters and by reference otherwise if you want decent performance.
Bultin and small types have to be passed by value to avoid useless dereference. And for builtin types like int, the fact of passing them by reference instead of by value prevent them to be stored in register which decrease performance.
In your code for example, you should change cSoundIF(string message, float freq) at line 11 by cSoundIF(string const& message, float freq).
You can pass objects by reference, Stewbond, and that is, in fact, the preferred method of professional programmers. I would change your class, for example, to:
If you're passing to an external function, though, all you have to worry about is putting the variable in there. You can't specify how the function treats your variable, you can only provide your variable to it. You basically have to trust the library writer to know how to use your variable correctly.
You don't have to pass by const&, but it is preferred. If you want to be able to mutate the originally passed value (not a copy), then pass by ref. If you want to mutate a copy, then pass by value. All other times, pass by const&.
And let's be real. You can pass by const& and remove the const by const_cast.
Stewbond: As a matter of principle, anytime you're making a class, you should make your non-static functions virtual. This makes it so that any person that uses your code and creates a sub-class of your class (including yourself!) can actually force the function's actions to change to be different than that of the superclass. Example:
class Poly
{
protected:
int mHeight, mWidth;
double mArea;
virtualdouble setArea(constint& mHeight, constint mWidth); // Superclass setArea
public:
virtualvoid setHeight(constint& inHeight);
virtualint getHeight() const;
virtualvoid setWidth(constint& inWidth);
virtualint getWidth() const;
virtualdouble getArea() const;
};
double Poly::setArea(constint& mHeight, constint& mWidth)
{
return mHeight * mWidth; // Superclass returns height * width for area
}
// Other functions omitted for brevity
class Triangle : public Poly
{
protected:
virtualdouble setArea(constint& mHeight, constint& mWidth); // Triangle overrides superclass
};
double Triangle::setArea(constint& mHeight, constint& mWidth)
{
return (mHeight * mWidth) / 2; // Triangle setArea returns a proper triangle area calculation
}
Without having set it as virtual, the setArea from the triangle will still be used, but it will not override the Poly version, it merely hides it. This means that the Poly version is still accessible through some methods when you try to call triangle's setArea function. This is not generally considered to be desirable behaviour.
As a matter of principle, anytime you're making a class, you should make your non-static functions virtual.
eeeh. I don't agree with this. Why do you think most of the member functions in the standard library is non-virtual? Most classes are not meant to be inherited from so why use virtual? It just adds unnecessary overhead if you never going to override the function. If you are making a function virtual you probably want to make the destructor virtual as well.
Yes, the destructor should also be virtual. The only time you would not make something virtual is if you are explicitly attempting to prevent it from being overridden, such as is the case in the standard library.
Your own classes, unless you never ever intend to use them ever again, should be made virtual, so that you don't have to go back and modify your code repeatedly in order to 'write once; use always'
ciphermagi, C++ is not Java. If the default behavior is to be not virtual there is a good reason: a virtual call is much more costly than a non-virtual one because of the dynamic dispatch and if one class has at least one virtual method it add a vptr to the class. Generally you choose C++ over higer level languages for performance.
And let's be real. You can pass by const& and remove the const by const_cast
Are you serious? Why would you do such a stupid thing?