I want to know whether one of the following two class design choices is superior in terms of performance and/or maintainability or other concerns which would favor one approach over the other.
First approach:
The base class (parent) has a private data member and one pure virtual void function. The child class(childA) passes the parameter from it's default constructor to the parent and uses the parent's getter method to print out some other value.
Second approach:
The base class (oncle) consists only of the a virual destructor and a pure virtual method. The child class (nephew) has the stores the value as a private data member and has it's own getter function to perform some calculation.
Here is some code:
#include <iostream>
class parent{
public:
parent(int x){ _x = x; }
virtual ~parent(){}
virtual void calc( void ) = 0;
int getX( void ) { return _x; }
private:
int _x;
};
class childA: public parent{
public:
childA(int x): parent(x){}
void calc( void ){std::cout << "x sq: " << parent::getX()*parent::getX() << std::endl;}
};
class oncle{
public:
virtual ~oncle(){}
virtual void calc( void ) = 0;
};
class nephewA: public oncle{
public:
nephewA(int x): _x(x){}
void calc( void ){std::cout << "x sq: " << getX()*getX() << std::endl;}
int getX( void ){ return _x; }
private:
int _x;
};
int main(int argc, char *argv[])
{
parent *first = new childA(3);
parent *second = new childB(3);
first->calc();
second->calc();
oncle *foo = new nephewA(3);
oncle *bar = new nephewB(3);
foo->calc();
bar->calc();
delete bar;
delete foo;
delete second;
delete first;
return 0;
}
In short: the first approach puts the emphasis on the parent and the second on the child class.
So are there any quantifiable aspects which could help me select one of the two approaches?
Performance:
In general, performance questions depend very much on compiler's optimizer and should best be addressed by an ad-hoc benchmark.
Nevertheless, for this simple example, it's obvious that the performance of both approaches should be the same:
calc()
is a virtual call (indirect function call). The function calls twice the parent's getX(), which is a non virtual function call (ie every calc() knows at compile time which function it has to call) fully determined at compile time. calc()
is also a virtual call (indirect function call). The function calls twice the object's getX(), which is a non virtual function call, fully determined at compile time. In addition, the compiler can inline here the non virtual functions very easily. So that optimized code will certainly not even call the function but directly use the variable.
Maintenability
You should ask yourself how much the members (x/getX()) are really bound to the class in which they are defined, and how probable it is that each element of your design could evolve.
getX()
for children which should have a different behaviour. The only drawback would be that these children would still have a private x which would stay unused. If you have a couple of objects, this is not a serious issue. If you'd have millions of such objects in memory, this could be suboptimal. getX()
This is a very flexible design, especially if there are many different rules:
Conclusions:
As you see, there is no single best answer. It all depends on the real relationqship between the classes and the members.
Some examples:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.