in my mfc souce code, there are some classes, which are multi-inheritance. Like:
class CGraphComboBox:public CComboBox, public virtual CGraphBaseClass
class CGraphFrame:public CFrameWnd, public virtual CGraphBaseClass
class CGraphPanel:public CWnd, public virtual CGraphBaseClass
class CGraphBaseClass is like:
class CGraphBaseClass
{
public:
typedef int(*BaseClassWndCallbackFunc)(CGraphBaseClass* base_class, void* param);
public:
CGraphBaseClass(){};
virtual CGraphWnd* get_main_graph_window();
virtual void AppendMenuItems(CMenu* menu){};
void EnumerateParentWindows(BaseClassWndCallbackFunc enum_func, void* user_data);
};
One of their base class is MFC standard classes which I cannot modify(eg. CComboBox), another base class(CGraphBaseClass) is my own class.
The reason I make class CGraphBaseClass as virtual, is because in other location, I need to dynamic bind its functions.
like below code:
int AppendMenuForAllParents(CGraphBaseClass* base_class, void* param)
{
CMenu* menu = reinterpret_cast<CMenu*>(param);
base_class->AppendMenuItems(menu);
return 0;
}
in these classes, eg.CGraphPanel, there are some MESSAGE_MAP. eg:
BEGIN_MESSAGE_MAP(CGraphPanel, CWnd)
//{{AFX_MSG_MAP(CGraphPanel)
ON_WM_PAINT()//C4407
ON_WM_CREATE() //C4407
ON_WM_MOUSEMOVE()//C4407
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
because classes' multi-inheritance and virtual base class, there will be
warning C4407:cast between different pointer to member representations, compiler may generate incorrect code
in these message map.
meanings
#define ON_WM_CREATE() \
{ WM_CREATE, 0, 0, 0, AfxSig_is, \
(AFX_PMSG) (AFX_PMSGW) \
(static_cast< int (AFX_MSG_CALL CWnd::*)(LPCREATESTRUCT) > ( &ThisClass :: OnCreate)) },
would not generate the correct code.
My question is: how could I refactor the code, to avoid these multi-inheritance?
Related
as the title says, I'm stuck with polymorphism issue during the developing of my project. I've already searched online but no responses satisfy my doubts.
So the situation is the following:
defined base abstract class for messages, MessageBase defined an abstract class Message, defined a template class MessageBase that is derived from Message. The different messages are then derived from the MessageBase template class (I'll provide the headers to clarify)
wrote a method writeMessage(Message* message); that accepts a pointer to the base class from which MessageBase and then DerivedMessage(s) inherits.
The classes are defined as follows (report only header files):
//Message.hh
class Message{
public:
Message();
protected:
virtual void write() = 0;
virtual void read() = 0;
virtual void handle() = 0;
}
//MessageBase.hh
template<typename MessageType>
class Messagebase : public Message {
protected:
Handler handler;
public:
//define the three methods of base class
void write() { handler.write(static_cast<MessageType&>(*this);}
}
void read() { handler.read(static_cast<MessageType&>(*this);}
}
void handle() { handler.handle(static_cast<MessageType&>(*this);}
}
};
//class DerivedMessageX.hh
class DerivedMessageX : public MessageBase<DerivedMessageX> {
public:
...
void setValue(int x);
//other methods of that type of message
}
class Interface{
...
...
public:
void writeMessage(Message* message){
message->write();
}
}
When I try to call the write message, I perform something like this:
Message* element = new DerivedMessageX(); //where DerivedMessageX is one of the derived message types
element->setValue(x); //this raise an error, setValue is not part of class Message
interface->writeMessage(element); //here the compiler does not recognize that my "element" is of base type MessageBase and so it tells that it cannot find any prototype to call.
The exact error is: error: no matching function for call to 'writeMessage(DerivedMessageX* message)'
In my understandings of polymorphism, I know that I describe a base class, containing pure virtual methods, that will be common to all the derived classes, and the derived classes will implement them, along with other specific derived-class methods.
So I wrote the method in order to accept a pointer to a base-class type, that calls a method on that object that is implemented at base-class level. I've done this because, needing only to call a base-class method and because I did not want to rewrite N writeMessage methods, I thought that passing the derived message type created as described above could do the trick.
Can anyone point out where I am wrong?
Thank you guys!
EDIT
As requested, the writeMessage method is defined as follows:
int writeMessage(MessageBase* message){
message->write(); // the method write() is base class level
}
and the error says: error: no matching function for call to 'writeMessage(DerivedMessageX* message)'
EDIT
rewrote the question in a more complete way. sorry guys
There are a lot of things can may be missing if you dont provide a minimal version of your code.
Here is a snippet that does what you need and works:
#include <iostream>
class MessageBase
{
public:
// CTOR
MessageBase(){};
virtual void printType(){
std::cout << "MessageBase" << std::endl;
};
};
class DerivedMessageX: public MessageBase
{
public:
// CTOR
DerivedMessageX():MessageBase(){};
void printType(){
std::cout << "DeviredMessageX" << std::endl;
};
};
class Interface
{
public:
Interface(){};
void writeMessage(MessageBase *elem){
elem->printType();
};
};
int main()
{
Interface interface;
MessageBase *base = new MessageBase();
MessageBase *derived = new DerivedMessageX();
interface.writeMessage(base);
interface.writeMessage(derived);
return 1;
};
The output should be:
MessageBase
DerivedMessageX
How would someone solve such a problem with classes and type as least as possible code?
Here is what I have
Base interface for everything
class IWindow
{
public:
virtual void Refresh() = 0;
// another 100 virtual methods
// ...
};
This interface is used inside a library that has no idea about the concrete implementation.
Here is a version of the concrete implementation
class ConcreteWindow : public IWindow
{
public:
void Refresh() override {}
/// the other 100 overridden methods
};
Now we have another interface that adds some additional methods and also used inside that library.
class IDBDetail : public IWindow
{
public:
virtual void DoDetail() = 0;
};
and here is the main problem, when we create the concrete inmplementation for it
class IGDBDetailWrapper : public IDBDetail, public ConcreteWindow
{
public :
void DoDetail() {}
};
of course the concrete class IGDBDetailWrapper is abstract as well because it doesn't implement those 100 methods, but I don't wanna do that, I'd like just to reuse the implementation from ConcreteWindow, they are all working with the same window handle but this won't compile of course.
I can copy/paste those 100 methods from ConcreteWindow into IGDBDetailWrapper, but that's an overkill, cause I might have another 10 such new interfaces and concrete implementations.
What other pattern can I use here that would help solve the question and not re-implement those 100 methods again and again?
Thx
Your design is running into diamond problem.
Now we have another interface that adds some additional methods and
also used inside that library.
class IDBDetail : public IWindow {
public:
virtual void DoDetail() = 0;
};
From the description of your IDBDetail interface looks like IDBDetail should not inherit from IWindow. If its just about adding additional functionality then IDBDetail need not be a IWindow. It just needs to understand the IWindow. For example in order to make a monkey do a special things, a trainer need not be a monkey.
Decorator pattern may be what you are looking for.
First, if you are using Visual Studio there are refactoring tools that can help you with that automating what could be otherwise a tedious task, second:
To me is much pointless doing the same:
class IDBDetail : public IWindow
{
public:
virtual void DoDetail() = 0;
};
I would do that instead
class IDBDetail
{
public:
virtual void DoDetail() = 0;
};
Interfaces should be used to abstract away responsibilities, so cluttering a Interface with already hundreds of methods with additional methods is a symptom of bad design.
However you could leverage composition one time for all, so you create one time a class that resolve the problem for your, and you can later reuse that
class IDBDetailWithConcreteWindow: public IDBDetail{
IWindow * concreteWindow;
public:
IDBDetailWithConcreteWindow(IWindow * window){
concreteWindow = window;
}
void Refresh() override{
concreteWindow->Refresh();
}
}
And finally in any derived class you have just to implement methods from IDBDetail
IGDBDetailWrapper: public IDBDetailWithConcreteWindow{
public:
void DoDetail() override { }
}
The advantage with this solution is that if you have external constraints (like a bad designed pre-existing code base) you can still use it, while the upper solution will not work if you cannot change the IDBDetail interface.
#bashrc is right, but it should be possible to solve the problem with virtual inheritance:
class ConcreteWindow : public virtual IWindow {...}
class IDBDetail : public virtual IWindow {...}
This Wikipedia article on virtual inheritance states the solution as well.
You can use virtual inheritance. If we ignore fact should IDBDetail inherit from IWindow or not, we could use virtual inheritance to solve problem with current architecture:
class IWindow
{
public:
virtual void Refresh() = 0;
// another 100 virtual methods
// ...
};
class ConcreteWindow : virtual public IWindow
{
public:
void Refresh() override {}
/// the other 100 overridden methods
};
class IDBDetail : virtual public IWindow
{
public:
virtual void DoDetail() = 0;
};
class IGDBDetailWrapper : public IDBDetail, public ConcreteWindow
{
public :
void DoDetail() {}
};
Now compiler will use implementation for your 101 abstract method from ConcreteWindow
You have to override all the methods in abstract class, there is no other way. Actually you shouldn't create an abstract class of 100 methods here and that's it. Perhaps You can divide it in some smaller abstract classes? However, in this case IDBDetail should not inherit after IWindow and IGBDDetailWrapper also shouldn't inherit after IWindow - and we are here.
It will not solve your problem, but at least you can redirect execution yourself:
class IGDBDetailWrapper : public IDBDetail, public ConcreteWindow
{
public:
virtual void DoDetail() override { /*work here*/ }
virtual void Refresh() override { ConcreteWindow::Refresh(); }
//another 100 methods
};
You can make the block of such redirections as a compiler #DEFINE and repeat it as many times as you want.
Scenario: I Want to use the Parent methods in child. Is it possible to create a solution with two dialog classes as shown below?
//Parent is created using class wizard(inherited from CDialog)
class CDlgParent : public CDialog
//Child class created using class wizard(inherited from CDialog) and then
//changed the inheritance
class CDlgChild : public CDlgParent
just to exemplify
class A
{
private:
void privateMethod(){}
protected:
void protectedMethod(){}
public:
void publicMethod(){}
};
class B : public A
{
void methodB()
{
//privateMethod();
protectedMethod();
publicMethod();
}
};
just copy this in your code and you will see that it will compile.
If you uncomment the line, it will not compile anymore, giving an error like:
cannot access private member declared in class 'A'
So the only methods that you cannot use from B, that inherits from A, are the private methods, all the others can just be used normally
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?!
I want simulated interface sterotype in C++ using abstract class. But in Eclipse IDE I get "Multiple markers at this line
- The type 'Handler' must implement the inherited pure virtual method
'Handler::setNext'"
My question is Why this?.
Handler.h
class Handler {
public:
virtual void setNext(Handler &next) = 0;
Handler();
virtual ~Handler();
virtual void process() = 0;
public:
Handler *nextInChain;
};
Handler.cpp
#include "Handler.h"
Handler::Handler(){
}
Handler::~Handler(){
}
Oracle.h
#include "Handler.h"
class Oracle : virtual public Handler {
public:
Oracle();
virtual ~Oracle();
virtual void process();
virtual void setNext(Handler &next);
private:
};
Oracle.cpp
#include "Oracle.h"
Oracle::Oracle(){
Handler AQUI;//AQUI I get Multiple markers at this line
//- The type 'Handler' must implement the inherited pure virtual method
//'Handler::setNext'
}
Oracle::~Oracle(){
}
void Oracle::process(){
}
void Oracle::setNext(Handler &next){
}
This is incorrect:
Handler AQUI;
You cannot instantiate an abstract class.
What you want to do is define a pointer to Handler and assign it the address of a valid object from a child class, like Oracle.