Reputation: 121
I am trying to figure out how to arrange some classes. This is what I've got so far ...
The top of the inheritance hierarchy is (naturally) T:
(T.h)
namespace foo
{
class T
{
public:
virtual void method1(std::string a_parameter) = 0;
virtual void method2() = 0;
};
}
I have two sub-classes of T with some additional methods - here are the header files:
(A.h)
namespace foo
{
class A : public T
{
public:
virtual ~A() {};
virtual void method3() = 0;
//and a factory function
static A* gimmeAnAyy();
};
}
(B.h)
namespace foo
{
class B : public T
{
public:
virtual ~B() {};
virtual void method4() = 0;
//and a factory function
static B* gimmeABee();
};
}
The implementation classes are in the respective .cpp files:
(A.cpp)
namespace foo
{
class AImpl : public A
{
public:
A(std::string member_data) : m_member_data(member_data) {};
~A() {};
void method3()
{
//something really important, can't think of it right now ;-)
};
private:
std::string m_member_data;
};
A* A::gimmeAnAyy()
{
return new AImpl("this is an impl of A");
};
}
(B.cpp)
namespace foo
{
class BImpl : public B
{
public:
B(std::string other_data) : m_other_data(other_data) {};
~B() {};
void method4()
{
//something really important, can't think of it right now ;-)
};
private:
std::string m_other_data;
};
B* B::gimmeABee()
{
return new BImpl("this is an imll of B");
};
}
Now the compiler complains - rightly so - about the virtual functions method1() and method2() that I haven't implemented in AImpl and BImpl.
What I want is a TImpl class that both AImpl and BImpl can inherit from so that I don't have to implement method1() and method2() in two different .cpp files.
Is it possible? Am I out to lunch? Am I asking too many rhetorical questions for a StackExchange post?
Mike
Upvotes: 3
Views: 443
Reputation: 3707
Yeah, it is possible. Common practice is to use the following snippet:
template<typename Interface>
class TImpl : public Interface
{
public:
virtual void method1(std::string a_parameter) { /* implementation */ }
virtual void method2() { /* implementation */ }
};
And then inherit from it as follows:
class Aimpl : public TImpl<A>
{
public:
virtual void method3() { /* implementation */ }
};
class Bimpl : public Timpl<B>
{
public:
virtual void method4() { /* implementation */ }
};
You can put implementation of Timpl in cpp file, but then you have to explicitly instantiate it for every possible interface. This is done as follows in the cpp:
template<typename Interface>
void Timpl<Interface>::method1(std::string a_parameter)
{
/* implementation */
}
template<typename Interface>
void Timpl<Interface>::method2()
{
/* implementation */
}
template class Timpl<A>;
template class Timpl<B>;
Upvotes: 1
Reputation: 267
In the A and B classes declaration, the methods 3 and 4 are pure virtual, so in the definition file you shouldn't gives an implementation of them. In my understand A and B are leading the implementation of the T methods and their own virtual methods to other concrete classes who inherit from them. If you thing that A and B are concrete classes, put away the "= 0" from the following lines:
class A : public T
{
public:
virtual ~A() {};
virtual void method3() = 0; // <-- Here
//and a factory function
static A* gimmeAnAyy();
};
class B : public T
{
public:
virtual ~B() {};
virtual void method4() = 0; // <-- and Here
//and a factory function
static B* gimmeABee();
};
If doesn't want to implement the methods 1 and 2 of the T class, give an empty or a default implementation to them, in the T class or in the A and B classes.
But consider this, if you inherits from an interface, is expected that you IMPLEMENT that interface. :)
Upvotes: 0
Reputation: 13
since both of the son classes (A & B) don't have (method1, method2) then you don't have to use the virtual. you can easily provide a default implementation in the base class and then invoke and use these methods through the inheritance chain since the inheritance type here is public.
Upvotes: 0
Reputation: 153820
It seems your problem is the wrong believe that it is better to have only pure virtual
functions in your base class! Just get over it and provide a default implementation in T
. Although there are religious believes that is bad, there isn't any technical reason not to have it. Insisting in having only pure virtual
functions in base classes is like insisting in all music having to be 12-tone music!
Upvotes: 0
Reputation: 59997
Do not make method1 and method2 pure virtual functions. Give them an implementation!
i.e.
declare
class T
{
public:
virtual void method1(std::string a_parameter);
virtual void method2();
};
Define:
void T::method1(std::string a_parameter) { // Could use const/reference here perhaps
....
}
etc...
Upvotes: 0