TP wrote:
Hello,
I convert a Python/Qt program (PyQt) in C++/Qt.
The programmer has used the duck typing of Python, thus I would like
to have
duck typing in C++, in fact exactly what is described in the "best
answer"
at the following address:
http://stackoverflow.com/questions/289176/how-is-duck-typing-different-from-
the-old-variant-type-and-or-interfaces
(the "best answer" is the second post of the page, the one with a green
sign).
Is it possible in C++?
Thanks in advance,
TP
I've tried just for fun. This is probably a naive
imitation... I just used codepad therefore had
no other libraries (e.g. boost available).
Output:
Duffy quacked!
Donald quacked!
//code...
#include <iostream>
#include <algorithm>
class Duck
{
struct QuackIF
{
virtual void quack() = 0;
virtual QuackIF* clone() const = 0;
virtual ~QuackIF(){}
};
template <class T>
struct QuackImpl : QuackIF
{
typedef void (T::*QuackFunc)();
QuackImpl( T& receiver )
: receiver_( &receiver ),
f_( &T::quack )
{
}
virtual QuackIF* clone() const
{
return new QuackImpl( *this );
}
virtual void quack()
{
(receiver_->*f_)();//Quack!!!
}
virtual ~QuackImpl(){}
private:
T* receiver_;
QuackFunc f_;
};
QuackIF* duck_;
public:
Duck( const Duck& other )
: duck_( other.duck_ ? other.duck_->clone() : 0 )
{
}
~Duck(){ delete duck_; }
Duck& operator=( Duck other )
{
std::swap( other.duck_, duck_ ); return *this;
}
template <class DuckT>
Duck( DuckT* duck )
: duck_( new QuackImpl<DuckT>( *duck ) )
{
}
void quack()
{
if( duck_ ){ duck_->quack(); }
else
{
std::cout << "Quack!" << std::endl;
}
}
};
struct Daffy
{
void quack(){ std::cout << "Duffy quacked!" << std::endl; }
};
struct Donald
{
void quack(){ std::cout << "Donald quacked!" << std::endl; }
};
int main()
{
Duck duck = new Daffy;
duck.quack();
duck = new Donald;
duck.quack();
}
It is naive yes; spot the memory leaks. To fix: wrap receiver_ in a
shared_ptr (so clone still works).