Is this an example of bad design? - c++

I will start with my design:
class IOutputBlock{
public:
virtual void write(char *) = 0;
virtual bool hasMemory() = 0;
virtual void openToWrite() = 0;
};
class IInputBlock{
public:
virtual bool hasNext() = 0;
virtual IField *next() = 0;
virtual void openToRead() = 0;
};
class MultiplicationNode : public OperationNode
{
public:
MultiplicationNode(Node *l, Node *r);
~MultiplicationNode(void);
virtual bool hasNext();
IInputBlock * evaluate();
};
class IOBlock: public IInputBlock, public IOutputBlock{
virtual void write(char *);
virtual bool hasMemory();
virtual void openToWrite();
virtual bool hasNext();
virtual IField *next();
virtual void openToRead();
};
Inside the evaluate method i need to create an IOuputBlock to write data in the block.
I want the MultiplicationNode consumer just see method for iterate over the block (IInputBlock interface).
But ​​in the return of evaluate method, I have to perform a typecast.
Is this implementation correct? Or is it an example of bad design?
Can u suggest another design? Or maybe design pattern to help.
IInputBlock * MultiplicationNode::evaluate()
{
IOutputBlock *outputBlock = new IOBlock();
//need to write to outputblock
return (IInputBlock *)outputBlock;
}
I could also do this below, but I don't think it is right, because i was violation "program to an interface", and exposing unnecessary methods inside evaluate method from IInputBlock interface.
IInputBlock * MultiplicationNode::evaluate()
{
IOBlock *outputBlock = new IOBlock();
//need to write to outputblock
return outputBlock;
}

One option is to separate read and write classes (even if underlying data is shared):
class WriteOnlyBlock: public IOutputBlock{
// return new instance of something like ReadOnlyBlock
// potentially tied to same internal data
public: IInputBlock AsRead()...
}
This way you make conversion explicit and prevent callers from attempting to cast IInputBlock to IOutputBlock and minimize number of extra methods exposed by each class.

Related

C++ declaring an abstract class as friend class

When and why would you declare an abstract class as a friend class?
I am trying to read the source code of levelDb
It has an interface (abstract class) DB which does not have access to DB_Impl:
class DB {
public:
static Status Open(const Options& options,
const std::string& name,
DB** dbptr);
DB() { }
virtual ~DB();
virtual Status Put(const WriteOptions& options,
const Slice& key,
const Slice& value) = 0;
virtual Status Delete(const WriteOptions& options, const Slice& key) = 0;
virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0;
virtual Status Get(const ReadOptions& options,
const Slice& key, std::string* value) = 0;
virtual Iterator* NewIterator(const ReadOptions& options) = 0;
virtual const Snapshot* GetSnapshot() = 0;
virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0;
virtual void GetApproximateSizes(const Range* range, int n,
uint64_t* sizes) = 0;
virtual void CompactRange(const Slice* begin, const Slice* end) = 0;
private:
// No copying allowed
DB(const DB&);
void operator=(const DB&);
};
and the implementation DB_Impl.
In db_impl.h:
class DBImpl : public DB {
public:
... // implementation of the DB interface
private:
friend class DB;
... // internal methods and variables
}
Why is the abstract class DB declared as a friend class of DBImpl?
An abstract class can have (and often has) non-abstract parts, for example normal member functions.
In your example, DB may have some normal member function f() { /* ... */ }. Furthermore, the class design may be such that DB is aware of certain derived classes. This is often, but not always, a sign of broken class design. So f may actually take a DBImpl argument and need to access some of its private members. In such a scenario, friend achieves the desired results.
Here is a complete example:
class DBImpl;
class DB {
public:
virtual ~DB() {}
void f(DBImpl& db_impl); // DB is aware of a derived class
private:
virtual void virtual_function() = 0; // just to make the class abstract
};
class DBImpl : public DB {
private:
void virtual_function() override {} // just to make the class concrete
void g() {} // DBImpl wants only DB to be able to call this
friend class DB;
};
void DB::f(DBImpl& db_impl) {
db_impl.g(); // DB can call DBImpl's private member function
}
May be the static function DB::Open in DB class is using DBImpl private/protected member variables/function.
Also if you havent shown the complete DB class declaration here and it has extra code please check if there is any non pure virtual function of DB class, it may have instance of DBImpl and access to its private member variables. This function can be inherited in derived classes and if called using derived class instance it will work fine.
Hope this helps.

C++ passing base type to pure virtual function

i want to understand the behavior of pure virtual functions in derived class when passing to it an argument of same type as (abstract) base class.
to clarify the question, i took the following code from GeeksForGeeks and modified it:
namespace example {
enum Type {ENGINEER, MANAGER};
class Employee
{
private:
const Type worker;
public:
Employee(const Type& worker) : worker(worker) {}
virtual ~Employee {}
virtual void raiseSalary(const Employee&) = 0;
{ /* common raise salary code */ }
virtual void promote(const Employee&) = 0;
{ /* common promote code */ }
};
class Manager: public Employee {
private:
int degree;
public:
//<constructor>\\
virtual void raiseSalary(const Employee&)
{ /* Manager specific raise salary code, may contain
increment of manager specific incentives*/ }
virtual void promote(const Employee&)
{ /* Manager specific promote */ }
};
}
Now, how can we get access to the field degree in derived class Manager inorder to update his degree? since the passed argument to raiseSalary(Employee& employee) could be Manager or Engineer
I think there are two ways to handle that problem. Let's start with some really bad solution: using casting. In that case dynamic_cast. You can try to down cast a type. If dynamic_cast isn't able to do that it is going to return a null pointer or throw an exception (depends on wheather you cast a pointer or a value/reference type). But that approach is going to force you to adapt your casts as more Manager, Engineer types are going to come. You might also need to use friend to allow specific classes to access internals of others. friend is not going to be inherited in the hierarchy, so you are going to end up with many friends => broken, broken, broken :(
An alternative would be to use the Visitor Pattern: http://en.wikipedia.org/wiki/Visitor_pattern
Using the visitor pattern you can also make a base no-op visitor and finer grained Visitors to handle specific stuff. Just a small example (with specific visitors without derivation):
namespace example {
class SalaryRaisingVisitor;
class EmployeePromotingVisitor;
class Employee
{
public:
Employee() {}
//don't forget to implement the copy constructor: read more about rule of 3!!!
virtual ~Employee {}
virtual void accept(SalaryRaisingVisitor const&) = 0;
virtual void accept(EmployeePromotingVisitor const&) = 0;
};
class Manager: public Employee {
private:
int degree;
public:
//<constructorS>
virtual void accept(SalaryRaisingVisitor const& v)
{
v.visit(*this, degree);
}
virtual void accept(EmployeePromotingVisitor const& v)
{
v.visit(*this, degree);
}
};
class Engineer: public Employee {
public:
//<constructorS>
virtual void accept(SalaryRaisingVisitor const& v)
{
v.visit(*this);
}
virtual void accept(EmployeePromotingVisitor const& v)
{
v.visit(*this);
}
};
class SalaryRaisingVisitor
{
void visit(Manager& m, int& degree) //might be const if no internal state changes
{
//...
}
void visit(Engineer& e) //might be const if no internal state changes
{
//...
}
};
}
At the end as you deal with C++, try to avoid virtual functions :) and move everything to static polymorphism :)
You are getting the concept of virtual functions with classes wrong. The class "knows" what it is (via vtable), so you can just write it as class function, not as static global function. Each function inside the class knows all class variables, so you don't have to pass an object of the class.
namespace example {
enum Type {ENGINEER, MANAGER};
class Employee
{
private:
const Type worker;
public:
Employee(const Type& worker) : worker(worker) {}
virtual ~Employee {}
virtual void raiseSalary() = 0;
{ /* common raise salary code */ }
virtual void promote() = 0;
{ /* common promote code */ }
};
class Manager: public Employee {
private:
int degree;
public:
//<constructor>\\
virtual void raiseSalary()
{
//the Employed standard code
Employee::raiseSalary(); //This won't compile since you set the virtual function = 0
//Manager specific raise salary code
degree = 0; //this lazy bastards should do real work like coding stuff
}
virtual void promote()
{
Employee::promote(); //employee common code. This won't compile since you set the virtual function = 0
/* Manager specific promote */
degree = degree * 2;
}
};
Employee array[10];
array[0] = Manager(); //create a manager object on the stack
array[1] = Manager(); //create a manager object on the stack
array[0].raiseSalary(); //Only Mananer0 gets raiseSalary
/*the manager object in array[0] uses its virtual function
to the manager raiseSalary function. The Manager RaiseSalary function
in this case calls the base class raiseSalary function explicitly
via Employee::raiseSalary(); */
You should rather structure your code like this:
class Employee
{
virtual void raiseSalary() = 0;
virtual void promote() = 0;
};
class Manager: public Employee
{
virtual void raiseSalary()
{ /* Manager specific raise salary code, may contain... */ }
virtual void promote()
{ /* Manager specific promote */ }
};
int main()
{
Manager bob;
bob.promote(); // <--- Proper method in the Manager class will be called.
// Current instance will always have the right class.
}
In other words you should seek opportunity to pass the specific derived class as the this parameter. Unfortunately this will not work in complex cases when multiple params are needed. But well, this was the idea of the language designers. The perfect language is not developed yet.
I think that you can't and it's the wanted behaviour.
The only way to do this is to cast you argument (which is quite complicated in C++ since you have four different kind of casting). Other solution is to give to any employee a grade attribute.
Alexis.

C++ Cannot convert child* to parent* by assignment

Using the following two classes...
//pure virtual...
class Monkey
{
public:
virtual ~Monkey(){}
virtual void clearMonkeys() = 0;
virtual std::shared_ptr<std::vector<sf::Text>> getMonkeyListPtr() = 0;
virtual void addMonkey(String message,Vector2f position,float depthValue) = 0;
};
class NullMonkey : public Monkey
{
public:
NullMonkey () {/*Do Nothing*/}
virtual ~NullMonkey () {/*Do Nothing*/}
virtual void clearMonkeys(){/*Do Nothing*/};
virtual std::shared_ptr<std::vector<sf::Text>> getMonkeyListPtr()
{
//Do Nothing but...
//Return NULL shared pointer
std::shared_ptr<std::vector<sf::Text>> nullSharedPointer;
return nullSharedPointer;
//Of course I am ASSUMING I will check for NULL pointer...
}
virtual void addMonkey(String message,Vector2f position,float depthValue){/*Do Nothing*/};
};
...I have issues when casting.
Specifically I am using these classes as static members and have a situation where if one class is not available I use the Null class to fall back on to prevent app crash. It also adds the ability to hot-swap child classes for debug purposes.
Unfortunately the following...
class ServLoc
{
public:
ServLoc();
static void initialize()
{
theMonkey = &theNullMonkey; //Error here
}
//...
static Monkey* theMonkey;
static NullMonkey theNullMonkey;
};
...throws 'cannot convert NullMonkey* to Monkey* in assignment'.
I should also add add I have defined the static members in the .cpp file
NullMonkey ServLoc::theNullMonkey;
Monkey* ServLoc::theMonkey;
The funny thing is I have used similar classes in similiar situations before and did not get this error. I am at a loss. It is probably something simple but still...
In fact I implement a log class using this method. It means I can hot-swap various forms of logging (including the null logger to disable logging) and have access to the logger wherever by just using the ServLoc static members...
class Logger
{
public:
virtual ~Logger() {}
virtual void log(const logType type,const char *message) = 0;
//...
};
class NullLogger : public Logger
{
public:
virtual ~NullLogger() {/*Do Nothing*/};
NullLogger() {/*Do Nothing*/};
virtual void log(const logType type,const char *message) {/*Do Nothing*/};
//...
};
This when used in same way in ServLoc as shown above works fine!?
Any ideas?
Regards
Edit - Fixed spelling mistakes
I suspect (could you clarify?), that you are calling the static function initialize() from another statically initialized class? Since this would all be done at program startup (and C++ does not guarantee any static initialization order between files), initialize may be called before ServLoc::theNullMonkey; has been constructed?!

C++ template method and obtaining result - design

I've such an interface class:
class MyInterface
{
public:
virtual void DoStuff() = 0;
virtual Result GetResult() = 0;
};
and simple abstract method, which realizes template pattern:
class Abstract: public MyInterface
{
public:
void DoStuff()
{
DoAFoo();
BakeAPie();
PrepareResult();
}
virtual DoAFoo() = 0;
virtual BakeAPie() = 0;
virtual PrepareResult() = 0;
};
And here comes my question. The method GetResult() should be implemented by every concrete implementation of Abstract? There would be a lot of such subclasses.
Or it should be handled in the Abstract class? Like this:
class Abstract: public MyInterface
{
public:
....
GetResult()
{
return m_result;
}
private:
Result m_result;
}
But how can I ensure, that Abstract subclasses will fill m_result within PrepareResult()?
You should ask yourself this question: "Is storing the result in a member and returning that member from GetResult() the only sane implementation of GetResult()? Some generally possible alternatives could be:
Compute the result on demand each time GetResult() is called.
Caching more than one result somewhere and returning the proper one from GetResult() based on circumstances.
Something else...?
Without knowing your exact problem, we cannot answer this, only you can.
If you arrive at the conclusion that yes, storing a single result in a member and returning it is the only sane approach, you can go ahead and implement GetResult() in Abstract, because then everybody else would be doing the exact same thing anyway. And to guarantee correct behaviour of PrepareResult(), you can change the interface as follows:
class Abstract: public MyInterface
{
public:
void DoStuff()
{
DoAFoo();
BakeAPie();
m_result = PrepareResult();
}
virtual void DoAFoo() = 0;
virtual void BakeAPie() = 0;
virtual Result PrepareResult() = 0;
virtual Result GetResult()
{ return m_result; }
private:
Result m_result;
};
Note that I'd suggest you mark GetResult() as const in MyInterface (and so in Abstract as well). It makes sense for this to be a const function.
You should implement GetResult in MyInterface, add a Result property in this class and its constructors.
Or you should delete this function in the interface and implement it in a subclass. Because if the interface doesn't hold this property, it may means that the interface knows too much.

C++: disallowing virtual function in derived class at compile vs runtime

I have a parent class RO that has a method void setup(const int* p). I need a child class RW to have same method that allows non-const pointers only.
I do it by creating two methods in class RO and disallowing one of them in class RW:
class RO
{
public:
void setup(int* p) { DO SMTH }
virtual void setup (const int* p) { RO::setup( const_cast<int*>(p) ); }
// the rest...
void read() const;
};
class RW : public RO
{
public:
virtual void setup (const int* p) { throw SMTH }
// the rest...
void write();
};
I'd like to be able to disallow RW::setup at compile time when possible. I.e.,
const int* p;
RO* ro = new RW;
ro->setup(p); // Throw at run time, since it can be unknown
// at compile time that ro points to RW and not to RO.
RW* rw = new RW;
rw->f(p); // Disallow this at compile time, since it is
// known at compile time that rw points to RW.
Is there a way to do it?
Use private instead of public inheritance. Make methods of the parent class available in the child class using the using keyword.
Public inheritance is meant for situations where someone who uses a parent class object might as well use a chid class object (look up Liskov substitution principle for details). Your requirement breaks that, so it's no case for public inheritance.
It sounds like class RO has an invariant: "Never modifies *p" (even though it does a sneaky const_cast on p). If class RW violates that invariant, it CANNOT be a subclass of class RO.
I'm guessing what you really want is something more like:
class Readable {
public:
virtual ~Readable();
virtual void read() const = 0;
};
class RO
: public Readable {
public:
void setup(const int* p);
void read() const;
private:
const int* m_p;
};
class RW
: public Readable
{
public:
void setup(int* p);
void read() const;
void write();
private:
int* m_p;
};
And if the followup question is: "What about DRY? Now I have to implement read() twice?", note that you can define a static member function in base class Readable something like:
static void do_read(const int* p);