Sign in to follow this  
Boder

Log Class

Recommended Posts

In C++ * Does std::vector call the copy constructor when it resizes or does it just do a direct data copy? * Can you do polymorphism without pointers? Without virtual functions? * Can I make a static operator() ? For my log manager, you can add different log types, so I was thinking either inheritance or template classes. The template class would just be a wrapper for a log class that supports certain functions. Then I could pass the templated class to the manager. Otherwise the manager could store base class pointers. * Which would you choose? The second option has some overhead. * For template classes I have to define the class in the header?

Share this post


Link to post
Share on other sites
std::vector will use the copy constructor and assignment operator where appropriate.

You can use polymorphism with references, but virtual functions are more or less necessary unless you want to implement the same functionality manually (not recommended).

operator() must be a non-static member.

Not clear on what you mean by your template implementation.

Template classes don't need to go into the header if your compiler implements the export keyword (practically none do) or if you use explicit template instantiation. However, in practice it's usually best to put the implementation in the header or some kind of inline file.

Share this post


Link to post
Share on other sites
I'm wondering about std::vector, since it seems unnecessary to call the copy constructor (this is different from operator = ?). We can guarantee that there will only be one of the final object in the new allocated memory, so we aren't really copying, we are just moving.

Share this post


Link to post
Share on other sites
1) I don't believe this is defined by the standard. I don't feel like looking it up right now. To be on the safe side, I would say "Don't rely on either behavior."
2) A little; if you aren't comfortable with it you should probably read some additional books on the language. Some forms of polymorphism, such as overloading, can be done without pointers. For example, foo::bar(int) and foo::bar(double) are polymorphic functions. Other forms, such as passing in a subclass and using its functions, require pointers. Virtual functions are about the only way to take advantage of subclasses.
3) Nope.
4) I would choose neither. See below.
5) Not necessarily. There is some variation between compilers on this issue, and you should check the documentation for your system.


Why not use one of the logging classes already out there (and [google]) that are debugged, often thread safe, and (in many cases) generate output readable through your debugger or operating system?

Some of the classes on that site will accept any object, and assuming you have a properly written operator<< for output, will display quite a bit of good stuff.

You can do some really nice things withe the TRACE macro or System.Diagnostics.Trace .NET class if you are doing managed c++. Some of those libraries also take advantage of that.

Share this post


Link to post
Share on other sites
std::vector needs to call the copy constructor otherwise it wouldn't play nicely with classes that did things like RegisterInstance(this) in the constructor. If your copy constructor can be implemented in terms of a memcpy(), you're free to implement it that way yourself. Also, keep in mind that this behavior may change with the addition of move constructors in the next version of the C++ standard.

Share this post


Link to post
Share on other sites
Here is an example.

class BMPWrapper:
BMPHandle handle
BMPWrapper():
handle = LoadBMP(FILE_NAME)
copy(BMPWrapper &rhs):
// need to copy
handle = LoadBMP(rhs.BMPHandle.filename)
~BMPWrapper():
freeBMP(handle)


Here if we are truly making a copy, we need to load the BMP again. If we are just shuffling around the class in memory, it is not necessary. But yet this would not be efficient in a vector if it loaded all the BMPs every time the vector is resized.

So the solution would be to use memory managed handles, and only specifically duplicate when necessary? Or maybe store pointers in the vector.

Share this post


Link to post
Share on other sites
Things with expensive copy construction/assignment semantics don't really belong in std::vectors. You can store (smart) pointers to objects instead, or use reference counted smart pointers for the implemenation of your object.

Share this post


Link to post
Share on other sites
Maybe you can comment on which way is better? P.S. they probably won't compile, I am just looking at the idea.

Edit: In writing this, I am even wondering if it possible to use a template class to define an interface like this.

// template

template <class T>
class Logger {
T log;
int setPriority(int x) { T.setPriority(x); }
int logString(const string& str) { T.logString(str); }
}

class LogManager {
list <Logger <?> > logList;
}



// base class

class Logger {
virtual int setPriority(int) = 0;
virtual int logString(const string&) = 0;
}

class LogManager {
list <Logger> logList;
}

Share this post


Link to post
Share on other sites
The first one won't compile and the second one won't work since you're trying to store polymorphic objects by value. If you want the second to work you'll need to store (smart) pointers to your log objects.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this