Reputation: 180
I have a working interface for two programs (ProgramA
and ProgramB
) that I would like to improve decoupling both programs as much as possible. The case that I want to cover is making a call from ProgramA
to a class from ProgramB
(Compute_Prop
) that can only be initialized with some arguments which I do not now in advance. Hence, I use a pointer in the header. Currently, I have something like this:
interface.h
#include "programB.h" // loads Compute_Prop
class Compute {
public:
Compute();
Compute(targ1 arg1, targ2 arg2);
~Compute();
// some methods ...
private:
Compute_Prop* compute;
};
interface.cpp
#include "programB.h"
#include "interface.h"
#include "programA.h"
Compute::Compute() = default;
Compute::~Compute() {
delete compute;
}
Compute::Compute(arg1, arg2) {
// do something ... to get data
compute = new Compute_Prop( &data, arg2 );
}
Then, I try to imitate the PIMPL idiom with the following
interface.h
#include "programB.h" // loads Compute_Prop
class Compute {
public:
Compute();
Compute(targ1 arg1, targ2 arg2);
~Compute();
// some methods ...
private:
class PIMPL;
PIMPL* compute;
};
interface.cpp
#include "programB.h"
#include "interface.h"
#include "programA.h"
Compute::PIMPL = Compute_Prop;
Compute::Compute() = default;
Compute::~Compute() {
delete compute;
}
Compute::Compute(arg1, arg2) {
// do something ... to get data
compute = new Compute_Prop( &data, arg2 );
}
but the compiler says:
error: expected unqualified-id
Compute::PIMPL = Compute_Prop;
^
I guess that it has something to do with Compute_Prop not having
an empty constructor. I can't come up with something that works. What should I do? Something like a pointer to a pointer, maybe? As a restriction, I cannot modify programB
.
Note: As it is probably already clear from above, my understanding of low level C++/C is scarce.
EDIT: I introduced the corrections suggested by @n.m. and @Matthieu Brucher
Upvotes: 1
Views: 875
Reputation: 180
I may have come across a simple solution. I post it here so you can judge if it is adequate, or even if it can be improved --- sure. I am convinced that runtime polymorphism is not needed, not even polymorphism. The member variable compute
is going to be a pointer to a Compute_Prop
type anyway. Then, given that performance is critical here: why running the extra overhead of virtual member functions?
The point here is to reach an implementation that hides the inclusion of Compute_Prop
without loosing performance. How? This particular solution uses a templated class and then explicit instantiation. The point is that instantiation can be done in the implementation. Got it from a Fluent C++ blog post. Also, this post has hints for how the implementation should be done. A prototype would be:
interface.h
template <typename T>
class Compute {
public:
Compute();
Compute(targ1 arg1, targ2 arg2);
~Compute();
// some methods ...
private:
T* compute; // No need to state that is going to be T:=Compute_Prop
};
interface_impl.h
#include "interface.h"
#include "programA.h"
template <typename T>
Compute::Compute() = default;
template <typename T>
Compute::~Compute() {
delete compute;
}
template <typename T>
Compute::Compute(arg1, arg2) {
// do something ... to get data
compute = new T( &data, arg2 );
}
interface.cpp
#include "interface.h"
#include "interface_impl.h"
#include "programA.h"
#include "programB.h" // loads Compute_Prop
int main(int argc, char** argv) {
template class Compute<Compute_Prop>;
}
Another related question that might be useful for those with the same dilemma.
Upvotes: 0
Reputation: 1150
Your implementation should use an interface (or in fact a class with only abstract methods) as a base class. You cannot assign types in C++. You can only create typedefs and aliases, like that:
using PIMPLType = Compute_Prop;
However this won't work in your case. This is how it should be implemented (also with possibility of multiple implementations):
class IImplementation
{
public:
virtual void saySomething() = 0;
};
class ImplementationA : public IImplementation
{
public:
virtual void saySomething() override {
std::cout << "A";
}
};
class ImplementationB : public IImplementation
{
public:
virtual void saySomething() override {
std::cout << "B";
}
};
class Foo {
IImplementation *pimpl;
public:
Foo()
: pimpl(new ImplementationA)
{}
~Foo() { delete pimpl; }
void saySomething() {
pimpl->saySomething();
}
};
Upvotes: 1