I'm doing some more C++ learning here, and I have some questions about cleaning up a vector that contains abstract base classes.
I created a simple "console" that you can feed a string, and have that string logged in a number of different ways. For example, you could tell the console to print "Hello world" and that string would be written to a string buffer, a file, and maybe even a database. The point is that the string can be logged in a variety of ways. I wanted the usage to feel something like this:
1 2 3 4 5
|
console.addLogger(stringLogger)
console.addLogger(fileLogger)
console.addLogger(databaseLogger)
consol.print("Hello world!")
|
So far I have created an abstract base class based on the tutorial on this website (
http://www.cplusplus.com/doc/tutorial/polymorphism.html). This class is called Logger. Logger is extended by another class called StringLogger, which uses a stringstream internally.
The Console class contains a
private vector<Logger*>
. It also has a function
addLogger(Logger* logger)
. My question is this:
When the destructor of the Console is called, should I have it delete all the Logger* instances in the vector, or should I expect the user of these classes to do that himself?
This question is causing me grief because I can imagine the class being used two ways:
Way 1:
1 2 3 4 5 6 7 8
|
StringLogger logger;
Console console;
console.addLogger(&logger);
// Send text to the StringLogger
console.print("This is a test");
console.print("This is also a test.");
|
If used this way, deleting the Logger* instances held by the vector causes a crash since new was never used. However, if used *only* in this manner, with new never being used, the Console would not need to delete anything.
Way 2:
1 2 3 4 5 6
|
Console console;
console.addLogger(new StringLogger());
// Send text to the StringLogger
console.print("This is a test");
console.print("This is also a test.");
|
In this case, deleting from the destructor of the Console makes it so the user does not have to manually delete anything. However, if someone uses the "address off" technique in Way 1, the program will bomb when it starts deleting things.
So, from a best practice sort of perspective, which is a better design? Deleting Logger*'s for the user and expecting him to use new (and avoiding address of), OR deleting nothing, and expecting the user to use address of and clean up after himself if he uses new?