Reputation: 49
I'm trying to work with my own little framework(only for interest actually:) ) recently. I'd like to abstract an interface to describe a process with an input and an output. So I defined a class BaseInput
and a class Baseoutput
. And here is the interface.
class IProcess
{
public:
virtual void Proc(BaseInput &input) = 0;
};
And here is my problem. The classes derived from IProcess
have to make BaseInput
as its argument's type according to the standard of C++. I expect the subclasses could be like this(I know it's wrong):
class ProcessA : public IProcess
{
public:
void Proc(MyInput &input) override;
};
I know this couldn't compile correctly. And I also know It could convert to a MyInput
pointer in ProcessA::Proc
. I considered Dependency Injection but I don't know whether it could solve my problem.
How do you guys solve such kinds of problems in the real project?
P.S. I actually found a similar situation here
Edit 1:
Well, I'm extremely sorry for my wrong expression. And thanks for all you guys' helping. MyInput
actually brings some data like this:
class MyInput : public BaseInput
{
public:
//... some functions
std::vector<int> m_Data;
};
AKA the argument's type should be MyInput&
if I need to access m_Data
from proc
without any pointer converting. What I want to achieve is architecture just like .NET Core MVC
. An input worker class accept different input(from files, internet or serial ports...), pack them into classes derived from BaseInput
and give it to some process classes derived from IProcess
(maybe there also could be some middleware) and finally return a result packaged by output classes derived from BaseOutput
.
It might be a really dumb architecture. I'm also wondering how to make it better. I had also considered not to pack those input. But I don't know how :-x
Thanks to all you guys again.🙏
Upvotes: 0
Views: 90
Reputation: 6805
Actually, MyInput
must inherits BaseInput
. Then, ProcessA::Proc
must have the same protoype than the IProcess::proc
that it is supposed to override (So it must take a BaseInput
as parameter too).
By using polymorphism, you will be able to pass a MyInput
when calling the function since you passed a reference and that MyInput
inherits BaseInput
.
Here is an example:
.h:
class BaseInput
{
public:
virtual ~BaseInput();
virtual void display();
};
class MyInput : public BaseInput
{
public:
void display() override;
};
class IProcess
{
public:
virtual ~IProcess();
virtual void proc(BaseInput & input) = 0;
};
class ProcessA : public IProcess
{
public:
void proc(BaseInput & input) override;
};
.cpp:
BaseInput::~BaseInput()
{}
void BaseInput::display()
{
std::cout << "BaseInput::display()" << std::endl;
}
void MyInput::display()
{
std::cout << "MyInput::display()" << std::endl;
}
IProcess::~IProcess()
{}
void ProcessA::proc(BaseInput & input)
{
input.display();
}
main:
int main()
{
MyInput mi;
ProcessA pa;
pa.proc(mi); // Pass a MyInput
return 0;
}
The output is (as expected):
MyInput::display()
EDIT (answer to question's edit 1):
You have two solutions.
Either you defines in BaseInput
the required methods to be implemented by every input type (as I did with display()
). In your case, it could be a getData()
member for example.
Or you will have to dynamic_cast
your given BaseInput &
into a MyInput &
.
Keep in mind that if dynamic_cast
fails with pointers, it returns a nullptr
, but if it fails with references, it will throw a std::bad_cast
exception.
As you use references, you will have to catch the exception in case of potential fail (if another type of input is given).
Upvotes: 2