It seems to be the prevailing opinion that using protected data members is a bad idea. I'm wondering what a good alternative would be in a specific case.
Take the following class called CModule, which represents a audio module (Amiga-style tracker music). Many different module formats exist but the only difference between them is in file format (Loading) and audio effects handling. CModule holds all the common functionality, the derived classes implement loading and effects for each specific format.
class CModule
{
public:
CModule(string Filename); //Song file name to load.
//Common methods...
void Play();
void Stop(); //Etc...
protected:
//Derived class should implement these with format specific code.
//Base class code calls these when needed.
virtual void Load()=0;
virtual void Effects()=0;
//Song information/data.
vector<CInstrument> Instruments;
vector<CPattern> Patterns;
//And much, MUCH more...
};
Almost all the data members are protected since the derived class's Load() function needs to fill them all. This is considered bad since it can break encapsulation if someone derives a class from the derived class. What would be the proper way to solve this problem? I've already found that using getters/setters is considered bad too.
Many thanks to anyone taking the time to read this :)
There's nothing wrong with using protected data members if using private won't work for your solution, using public data members however is almost never a good idea (however it can be sometimes too).
I would probably make your vectors private in this case but simply create getter and setter methods. Something along the lines of:
class CModule
{
public:
CModule(string Filename); //Song file name to load.
//Common methods...
void Play();
void Stop(); //Etc...
protected:
//Derived class should implement these with format specific code.
//Base class code calls these when needed.
virtual void Load()=0;
virtual void Effects()=0;
void AddInstrument(CInstrument instrument)
{
Instruments.push_back(instrument);
}
Instrument GetInstrument(int index)
{
return Instruments[index];
}
int InstrumentCount()
{
return Instruments.size();
}
private:
//Song information/data.
vector<CInstrument> Instruments;
vector<CPattern> Patterns;
//And much, MUCH more...
};
This is a start just for instruments, you'll also have to take a similar approach with patterns. Alternatively you could also just pass back the vector but this is a little more encapsulated.
Also note that I am doing this off the top of my head and haven't tested it against typos of whatever but hopefully it conveys the idea.
Related
It seems to me that my class is too big and complicated, I would like to reduce it. Can I use inheritance in this way, given that I created the InitCar class only to inherit it and am not going to use objects of this class explicitly.
Before refactoring. People and License are not my own classes, I cannot change them.
class Car
{
public:
void Move();
void SpeedUp();
void SpeedDw();
//More other
private:
int speed = 0;
std::string name;
int id = 0;
People owner; // not my own class
License license; // not my own class
void InitCarFromConfig()
{
//Here I read the data from the file
}
void InitOwner()
{
//Here I init the People owner
}
void InitInspection()3
{
//Here I init the License license
}
};
After refactoring
class InitCar
{
protected:
std::string name;
int id = 0;
People owner; // not my own class
License license; // not my own class
void InitCarFromConfig()
{
//Here I read the data from the file
}
void InitOwner()
{
//Here I init the People owner
}
void InitInspection()
{
//Here I init the License license
}
};
class Car : InitCar
{
public:
void Move()
{
InitOwner();
}
void SpeedUp();
void SpeedDw();
//More other
private:
int speed = 0;
};
Is this use of inheritance acceptable and are performance issues possible?
Although it is true that you can use inheritance to reduce the size of you classes and reduce code duplication for other classes (which can also inherit InitCar for similar base functionality), it is actually not a good idea.
Functionality-wise, it does work, it does reduce code duplication and class sizes. However, it is a bad design, because it uses inheritance wrong, and breaks concepts of "clean code".
When you create a class, you create an entity which represents something. Inheritance create relations between those entities. Saying that Car inherits InitCar is saying that Car is a sort of InitCar, which logically makes no sense, because InitCar is just a helper class.
You can solve this if the base type was an actual entity, like Vehicle, and you had multiple vehicles. However, your InitClass is specifically intended to split you code, so it doesn't actually make a Vehicle, renaming it won't fix the design.
Composition over inheritance
A well known concept in "clean code", saying that it is better to hold functionality helping classes as variables in the class, rather then inherit from a base class. It is both more flexible for switching implementations, and does not abuse the purpose of inheritance:
class Car {
public:
void Move();
void SpeedUp();
void SpeedDw();
//More other
private:
int speed = 0;
std::string name;
int id = 0;
People owner;
License license;
HelperClass helper; // new class for initing..
void InitCarFromConfig()
{
//data = helper.InitCarFromConfig();
}
void InitOwner()
{
//owner = helper.InitOwnerForCar(param);
}
void InitInspection()
{
//data = helper.InitInspection(param);
}
};
Now we simply delegate our calls to the helper class (whose name is just a stub, you should have a name matching what it does, or maybe several classes). So we do save some space, we don't abuse inheritance and typing, and we now actually have flexibility in implementation, since now we can replace the instance of helper and get a new logic.
How do we init helper? Usually receiving via the constructor is the best idea. But you can create inside the class if you really want to.
Best design for your case
But is it the best design here?! No actually. Because the real problem in the class is the existence of the Init_ methods within the class.
When creating a class, it is important that when the constructor finishes running, the class is completely initialized. When it is not, we create several problems:
Risk a chance that the class is used, and some properties/methods are not complete for use, causing errors
Complexity of the class is increased, making maintenance harder (which is what you pointed as the issue for you).
Limits the users of the class from flexibility in its creation, thus limiting the design options for using the class. Creating tests for example, will be a nightmare.
Very risk for multithreading use, and harder to handle
Instead than, what we can do is receive all the data we need to operate from the constructor, and simply store it:
public:
Car(std::string name, id, People owner, License license);
Now comes another issue: what if it is difficult to perform initialization. After all you have 3 methods for initializing your class, so could be not easy for users. This is were the Factory design pattern comes in. We will create a class, named CarFactory (or so) and use it to create our classes. Within it, it will have all the logic to init the class data:
class CarFactory {
public:
Car* CreateCar(params_from_user) {
// init data
return new Car(data);
}
};
What did we accomplish with this:
We made Car smaller and less complex
We allowed users more options about how to use Car
We maintained the Init option from earlier, to help create Car
Our code is a lot easier to look at and maintain because it is separated logically, and classes are small
Car is fully initialized after constructor call
I have a generic question on C++ class design. For example I have a need for a packet generator. So given a type of packet I have to generate the packet of that type. So I have a base packet generator class.
Approach 1:
class BasePacketGenerator {
public:
virtual Packet* generatePacket (int type); // implements the generic case
// hence not pure virtual
protected:
//
// Common functionality for all types
//
virtual void massagePacket (Packet& pkt); // called by generatePacket
// but needs special handling for
// some types
virtual void calculateCheckSum(Packet& pkt); // called by generate packet
...
};
Derived classes to handle each type:
class Type1PacketGenerator : public BasePacketGenerator {
public:
// Dont have to override any base class implementationa
protected:
void calculateCheckSum(Packet& pkt) override;
};
class Type2PacketGenerator : public BasePacketGenerator {
public:
Packet* generatePacket(int type) override;
};
Here for Type1 generator, we are using polymorphism. But the base-class calls, the derived class functionality polymorphically. I wonder if this is a good Idiom? Or there should be a intermediator class
Approach 2:
class TypeHandler {
virtual Packet* setupPacket();
virtual void calculateCheckSum(Packet& pkt);
virtual void setupFields (Packet& pkt);
}
class PacketGenerator {
public:
TypeHandler *handler_; // lets say this is setup based on the type
Packet* generatorPacket(int type)
{
auto packet = handler_->setupPacket();
handler_->massagePacket();
handler_->calculateCheckSum(*packet);
return packet;
}
}
Is there any advantage with going with one approach or the other?
Approach1 is more flexible as it doesn't have to follow the same way of doing things. Eg: if Type2Generator doesn't need a checksum, it doesn't even have to call the calculateCheckSum() or if it needs some additional functionality, we don't have to add it to all Type generators.
But Approach 2 is more readable as all types do the things same way.
Modern design sensibilities tend to favor a very aggressive separation of concerns. As such, this leads to preferring base classes that are nothing but pure virtual function declarations.
Each class is responsible for 1 thing.
As such, your second approach is considered much preferable. The main reason (and the only one you really need) being: it makes it much easier to write proper unit tests.
Edit: mind you, it still looks a bit clunky, but this is more a matter for The codereview stackexchange, where you could get detailed feedback on your structure.
there is a post with a quite similar title here, but as I understood the actual problem there is different.
I would like to know if it is possible to force a user of a class i wrote to override a certain method but at the same time it should not be possible to call this method (but its only called from within my class).
For example, if I want to do the following:
class AbstrDataSource {
private:
int index;
protected:
int currentData;
public:
int getData(){return currentData;}
void loadData(int i){
// check valid index here
if (index != i){doLoad(i);}
this->index = i;
}
virtual void doLoad(int i)=0;
};
In loadData() I can check that the index is in a valid range and do some bookkeeping, while the actual loading has to be supplied by the user via overriding doLoad(). Because pure virtual methods are part of the interface, they are public, but how do I force the implementation of doLoad() to be visible only to my own class?
My idea was to hide the object in some wrapper:
class DataSupplier {
public:
DataSupplier(AbstrDataSource* s) : source(s){}
void loadData(int i){source->loadData(i);}
int getData(){return source->getData();}
private:
AbstrDataSource* source;
};
And instead of using the abstract class I use the wrapper:
int SomeCalculation(DataSupplier* a,DataSupplier* b){
return a->getData() + b->getData();
}
However, this does not really help. Lets say a second person provides a implementation of my abstract class:
class ImplDataSource : public AbstrDataSource{
public:
void doLoad(int i){this->currentData = i;}
};
Then a third person still has access to doLoad():
void main(){
AbstrDataSource* ads = new ImplDataSource();
DataSupplier* ds1 = new DataSupplier(ads);
DataSupplier* ds2 = new DataSupplier(ads);
ads->doLoad(10); // <- How to avoid this ??
ds1->loadData(12);
ds2->loadData(12);
SomeCalculations(ds1,ds2);
}
Maybe there is a way to achieve this by using access specifiers...?
EDIT: I already got some helpful answers, but I think I did not state my question clear enough. As long as ImplDataSource declares doLoad() as protected or private, everything is fine. However, looking only at AbstrDataSource, there is no hint that any implementation of doLoad() should be private (even if the abstract doLoad was protected or private the actual implementation can have any access). I would like to know if it is possible to somehow "enforce" any implementation of the abstract doLoad() to be private. Maybe I am just thinking too complicated and the easiest way would be to add a comment to the documentation of the abstract method ("implement as private or it may fail").
What you're trying to achieve is called the template method pattern and
I think the best you can do here is to delegate to the doLoad method the less "sensitive" behavior and put the loadData (and the part you wanna hide from the derived class) in private access
Make the method doLoad() protected, then it can only be called from within the superclass, and it overloads (and hides) the pure virtual method of the base class.
I'm currently learning C++ and for this I'm writing a simple image-converter.
I would like to have a base image class that contains different memorylayouts of the image, say DXTn or BMP.
How do I properly design my class that can contain these different datatypes?
Is there a better way of storing the memory in a (smart)pointer?
class Image
{
public:
void loadDXT() { }
void loadBMP() { }
private:
char* data1;
std::unique_ptr< char* > data2;
}
Or would it be better to derive a more specific classfrom a simple baseclass:
class baseImage
{
public:
enum imgType { BMP , DXT };
void load() = 0;
}
class BMPImage : public baseImage
{
//bmp specific stuff here
}
This isn't only specific to this imageclass, I'm in general curious how do I design classes that contain different data member.
Thank you.
I agree with jwg a virtual abstract interface would make your life easier.
For example:
class BaseImage//base class
{
public:
virtual void DoThingsRelatedToAllImages_1()=0;
virtual void DoThingsRelatedToAllImages_2()=0;
//...and so on and whatever else
private:
int DataUsedForAllImageTypes;
};
//this is our child class
class Bmp: public BaseImage
{
private:
int DataUsedOnlyForBmpTypeImages;
};
void Bmp::DoThingsRelatedToAllImages_1()
{
//Do Whatever this function should do for a bitmap
}
void Bmp::DoThingsRelatedToAllImages_2()
{
//Do Whatever this function should do for a bitmap
}
Just keep in mind than an abstract class cannot be instantiated because it has no implementation. If you go with a virtual class not an abstract class you in theory could have typeless image classes to work with if you needed it. all you would need to do is provide a basic implementation to your virtual class.
For example:
class BaseImage//base class
{
public:
virtual void DoThingsRelatedToAllImages_1();
virtual void DoThingsRelatedToAllImages_2();
//...and so on and whatever else
private:
int DataUsedForAllImageTypes;
};
void BaseImage::DoThingsRelatedToAllImages_1()
{
//Do Whatever this function should do for a base image
}
void BaseImage::DoThingsRelatedToAllImages_2()
{
//Do Whatever this function should do for a base image
}
//this is our child class
class Bmp: public BaseImage
{
private:
int DataUsedOnlyForBmpTypeImages;
};
void Bmp::DoThingsRelatedToAllImages_1()
{
//Do Whatever this function should do for a bitmap
}
void Bmp::DoThingsRelatedToAllImages_2()
{
//Do Whatever this function should do for a bitmap
}
Hopefully this was a helpful example.
I would also say that Template classes could be very useful but I will leave you to figure that out as I do not really want to go into that right now.
Good luck, Let me know if i can clarify anything i said.
I would say that the second method is definitely what you need. You are basically specifying an interface - what you would use an abstract class for in C++. The base class should contain all the functions that you think every image should be able to provide - probably as pure virtual functions since there is no 'general image' which implements these the same way for any image. (You might have things like common metadata which have the same structure for every image type, and these could be dealt with by methods in the base class.)
Then each class will implement the virtual functions based on its own private data stored in the way that makes sense for that type of image. If some image types share some, but not all operations, you could have several layers of inheritance, eg RasterImage inherits from Image and BMPImage and PNGImage inherit from RasterImage.
There are libraries around that do a lot of this stuff to permit rendering of graphs, vector objects, etc. into multiple formats. You probably don't want to use a big outside library since you are doing this to teach yourself, but you might like to look at how one is structured to get some ideas. (Note that some graphics libraries will justifiably have a much more complex and flexible structure then you probably want to imitate. If there are so many layers of abstraction and inheritance that you can't keep track of them, it might not be the best source to learn by example from.)
Good day to you all...
I'm working on a complex project on my company which I use some wringled Factory Design pattern in the project. Omiting the details; I have some classes (I call them "Devices") which can only be created by "Readers":
class DeviceBase // this is a virtual base class
{
public:
//some stuff
friend class ReaderBase; // this is OK and necessary I guess?
private:
DeviceBase(); // cannot create a device directly
//some more stuff
}
class Device1: public DeviceBase // some extended device
{
public:
//some stuff
private:
//some more stuff
}
class Device2: public DeviceBase // some other extended device
{
public:
//some stuff
private:
//some more stuff
}
Now the "Reader", which happens to be factory for devices:
class ReaderBase
{
private:
DeviceBase[] _devices; // to keep track of devices currently "latched"
public:
// some other methods, getters-setters etc ...
// this method will create the "Devices" :
virtual bool PollforDevice ( DeviceType, timeout) = 0;
}
Now, this is my factory class; but it's (as you can see) pure virtual. I have special Readers inherit from this one:
class InternalReader: public ReaderBase
{
public:
// define other inherited methods by specifics of this reader
bool PollforDevice( DeviceType dt, timeout ms)
{
switch(dt)
{
case Device1: { /* create new device1 and attach to this reader */ } break;
case Device2: { /* create new device2 and attach to this reader */ } break;
}
// show goes on and on...
}
}
class ExternalReader: public Reader
{
public:
// define other inherited methods by specifics of this reader
bool PollforDevice( DeviceType dt, timeout ms)
{
switch(dt)
{
case Device1: { /* create new device1 and attach to this reader */ } break;
case Device2: { /* create new device2 and attach to this reader */ } break;
}
// show goes on and on...
}
}
The reason I use this pattern is: I'm writing for a system that can have multiple of these "readers" attached at the same time and I must use them all at the same time.
And these "Devices": I can make theirs constructor public too, and everyone would be happy; but I want to make sure that they are not created by the code writers themselves (to make sure other coders of it)
Now the questions:
Should I explicitly declare in every "Device" that ReaderBase is a friend? Or just declaring at the base "DeviceBase" should be enough?
Should I explicitly put in every "Device" that the "Readers" inherited from the "ReaderBase" are also friends of these devices, or just putting ReaderBase is enough?
Instead of making whole "ReaderBase" class a friend, can I (and should I) just make the member method "PollforDevice" a friend? Knowing that it's a pure virtual method, would that make inherited copies friends as well?
I'm sorry that the question is a very long one, but I just want to make it clear.
Thanks in advance...
Why bother about constructability of pure abstract base classes like DeviceBase? It can't be constructed anyway if it is a properly designed contract or abstract base class. Unless you have to fit into some kind of framework which you didn't mention, just do the opposite of hiding, e.g.:
struct DeviceBase {
virtual void Foo() = 0;
virtual void Bar() = 0;
virtual ~DeviceBase() = default;
};
By the way, declaring the constructors or destructors private will very effectively make your class "sealed". If for some reason DeviceBase is not abstract (which were a serious design flaw in my eyes) make constructors protected not private. Where you need to bother, is the constructor accessibility of the concrete Device classes. Assuming that you are going to "publish" these implementation classes (i.e. their definitions are accessible to users of your library) and you wish to stress that direct construction is prohibited, use the "access idiom" (my invented name for this):
namespace impl_detail {
class DeviceAccess;
}
class ConcreteDevice1 : public DeviceBase {
friend class impl_detail::DeviceAccess;
// implementation of DeviceBase and all other stuff go
// into the "private" section
};
namespace impl_detail {
class DeviceAccess {
template< class TDevice >
static DeviceBase* Create()
{
return new TDevice;
}
};
};
In your Reader classes use impl_detail::DeviceAccess::Create to construct Device instances, e.g.:
// Your ExternalReader::PollForDevice...
switch (dt) {
case Device1:
return impl_detail::DeviceAccess::Create<ConcreteDevice1>();
case Device2:
// etc...
}
Long story short, best solution is to not publish concrete implementation classes at all, second best some kind of "psychological barrier" which restricts construction, e.g. of the above kind...
Should I explicitly declare in every "Device" that ReaderBase is a friend? Or just declaring at the base "DeviceBase" should be enough?
Should I explicitly put in every "Device" that the "Readers" inherited from the "ReaderBase" are also friends of these devices, or just putting ReaderBase is enough?
As friendship is not inherited (at either side of the friendship relation), the only way your scheme will work is when you declare friendship of every derived Reader in every derived Device. This creates a tight coupling between the Reader classes and the Device classes that is not a nice design.
3) Instead of making whole "ReaderBase" class a friend, can I (and should I) just make the member method "PollforDevice" a friend? Knowing that it's a pure virtual method, would that make inherited copies friends as well?
You could make ReaderX::PollforDevice a friend instead of the entire ReaderX class, but it won't help you much and only opens the door for hard to resolve circular dependencies.
Actually, it is quite hard to create a design where classes of hierarchy X can only be created by classes of hierarchy Y and no one else, without creating a tight coupling between the classes in both hierarchies.
My approach would be
First and foremost, educate your coworkers that if they want a DeviceX, then they can obtain it from a ReaderY and in no other way. Make sure this is enforced in code reviews.
All the other steps are just damage control.
Make sure only the BaseDevice class gets exposed to code outside the Reader's implementation.
Make the destructor of all Device classes protected. This ensures that Device classes can only be cleaned up by derived classes or friends (and automatically rules out stack allocation by non-friends). Should get someone to think twice if they accidentally try to use a Device class directly.
Make the ReaderBase a friend of DeviceBase and give ReaderBase a function to do the actual cleanup of a Device. This is needed to ensure Devices can be cleaned up.