Reputation: 23
The aim of the program was to generate simulation scripts of loudspeaker enclosures.
Thus I have a class speaker which define the speaker.
A parent class enclosure which contains common parameters of all enclosures.
Children class which have specials properties of themselves.
Using polymorphism and inheritance I obtained the first program which work perfectly fine but i need to recalculate basics properties of enclosure each time:
class speaker
{
}
class Enclosure
{
int m_boxHeight;
speaker * m_speakerBass;//...
public://some functions
}
class closedBox : public Enclosure
{
public:
closedbox(speaker &speakerbass):Enclosure(speakerbass)// some functions
protected:
int paramclosed1;//...
}
int main()
{
speaker speakerbass;
cout <<endl<< "Please choose in the available enclosure proposals" << endl;
cout << "1 Closed box enclosure" << endl;
// cout << "2 Bass reflex enclosure" << endl;
// cout << "3 and so on..." << endl;
int choice;
cin>>choice;
switch (choice)
{
case 1:
closedbox * ClBox2Simu;
ClBox2Simu= new closedbox(speakerbass);
delete ClBox2Simu;
break;
case 2:
//... same but with bassreflex class child
break;
default:
cout<<"Then good bye";
}
return 0;
}
In the case of my program the member data of the parent class could be given to the childen . I mean, the box dimension of the Enclosure
are the same in each child class bassreflex
or closedbox
.
Thus I would now if there is a way to:
create the parent class
do the first initial general calculations
create children with parent parameters (problem)
Which mean basically child=parent which is forbidden. In the idea of this code:
class speaker
{
public: // some functions
protected:
int fs;
int paramSpeaker2; //...
}
class Enclosure
{
public: //some common function
protected:
int m_boxHeight;
speaker *m_speakerBass //...
}
class closedBox : public Enclosure
{
public:
closedbox(); // some functions
protected:
int paramclosed1; //...
}
class bassreflex : public Enclosure
{
public:
bassreflex(); // some functions
protected:
int paramclosed1; //...
}
int main()
{
Enclosure initialBox;// calculate dimension,choose speaker...
closedbox * ClBox2Simu;
ClBox2Simu= initialBox;// child= parent which is forbidden
//do stuff concerning closedbox
delete ClBox2Simu;
bassreflex * BassReflex2Simu;
BassReflex2Simu= initialBox; //forbidden
//do stuff concerning bassreflex
delete BassReflex2Simu;
//... and so on for other child class using enclosure
delete initialBox
return 0;
}
Hope it's clear!
Upvotes: 1
Views: 2272
Reputation: 73376
The symptoms that you describe suggest a typical is-a vs. has-a, i.e. inheritance vs. composition problem.
In C++, the principle is to create the child objects. The construction process of the child is:
As soon as you have problem with this logic, it suggest that the inheritance is probably not the best approach. The usual advice in OOP is to prefer composition over inheritance. Inheritance should in principle only be used if the nature of the object doesn't change.
As I'm not familiar with your domain, here a typical and more familiar example:
class animal {};
class cat : public animal {}; // ok: a cat will always remain an animal
class person {};
class employee : public person {}; // bad idea: a person could have several job
// or change job or (hopefully temporarily) without job
// possible alternative
class job_t { string title, company; date from,to; ... };
class person { vector<job_t> jobs; ... }; // very flexible
In your case, I'd understand that Enclosure
has some general parameters, but there is a shape factor (I'd call this family) that determines how waves are communicated to the environment,and some other functions.
In this case you could go for:
class EnclosureFamily {
public:
double compute_volume_in_room() = 0; // abstract;
};
class Enclosure
{
public: //some common function
double compute_volume_in_room() {
return f->compute_volume_in_room(); // forwarding
}
protected:
int m_boxHeight;
speaker *m_speakerBass;
EnclosureFamily *f; // ok, but smart ponters should be preferred
};
class BoxEnclosure : public EnclosureFamily {
public:
double compute_volume_in_room() { ... };
};
This allows you to change the enclosure family as you want. By the way, this is an implementation of the strategy pattern.
If you really need to keep your original design, you could overwrite the parent class using casting to parent and making use of slicing effect:
*static_cast<Enclosure*>(BassReflex2Simu)= initialBox; // not forbidden but slicing
However I wouldn't advise going that way (keep in mind that it first would require proper implementation of the rule of 3 on the parent)
Upvotes: 1