duct typing and interface in C++

T

TP

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
 
A

Alain Ketterlin

TP said:
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++?

Come on, duck typing is a funny name for "no static typing, cross
fingers at runtime". There is no such thing in C++, which is a
statically typed, object-oriented language. This means that a call like
o.quack() in C++ will never crash at runtime with a message like "no
such method". You don't even have to write dozens of tests verify that,
it's guaranteed by the compiler.

Read about "interfaces", or "pure virtual classes".

-- Alain.
 
D

Dombo

Op 24-Jul-11 17:40, TP schreef:
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++?

I think the closest you can come to duck typing with C++ is using
templates. Whether that is a good idea or not is another question.
 
N

Nobody

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++,
Is it possible in C++?

Duck typing is just interfaces, which are just classes with no member
variables and only pure virtual methods.
 
B

BGB

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++?

yes, and it is also possible in C, but the "ideal" strategy will differ.

also, IIRC, Boost may offer something like this, if this is relevant.


but, other potential strategies:

using RTTI:
merits: reasonably simple and straightforward in C++, meshes well with
C++ style, ...
downside: depends on classes and is subject to compiler issues (may be
disabled by command-line options, or require a command-line option to
enable), and may potentially have drawbacks related to overhead, on some
systems (namely Windows), it may break violently across arbitrary
borders (say, if you make a DLL and then use the DLL from an EXE, the
RTTI may not actually work).

http://en.wikipedia.org/wiki/RTTI


using tagged references:
merits:
may be reasonably efficient;
very commonly used in implementing VMs (dominant strategy);
relatively C-friendly;
integers or floating point values may be directly encoded into
references (sometimes called fixnum and flonum);
....

downside:
may be more awkward to use (depending on details, requiring much added
manual boxing/unboxing/bookkeeping);
bit-twiddly and magic numbers.


using "magic pointers" (where one has a raw pointer, and types are
identified based on the pointed-to object or memory-address):

merits:
can be made fairly easy to use (depending on implementation details,
dynamic types in C++ can be made to have a "look and feel" almost as if
one was them in a dynamically-typed language);
are also relatively C friendly;
generally much easier to manage than tagged references;
it is often easier to extend the type-system in an ad-hoc manner;
may be made cast-compatible with struct or class pointers;
....

downside:
potentially less efficient and more complex to implement than tagged
references;
they are a less well-known strategy;
generally, fewer bits can be afforded to fixnum and flonum types (mostly
an issue on 32-bit systems).


or such...
 
B

BGB

Op 24-Jul-11 17:40, TP schreef:

I think the closest you can come to duck typing with C++ is using
templates. Whether that is a good idea or not is another question.

possibly, if one stays within static types.

however, given Python was mentioned, it is possible that "duck typing"
here was more in reference to the sort of dynamic type-system which
Python provides, which may be better handled via dynamic types than via
templates.


an advantage of templates vs dynamic types though is that they may allow
more compile-time type-verification, as well as higher performance, due
to a lack of run-time type-checking or dynamic method-dispatch
mechanisms or similar.

however, in terms of using them, they are very different beasts.
 
T

TP

Nobody said:
Duck typing is just interfaces, which are just classes with no member
variables and only pure virtual methods.

I have tried to convert the example of the webpage I mentioned:

#include <iostream>

class InterfaceDuck
{
public:
virtual void Quack() = 0;
};

class Daffy
{
public:
void Quack()
{
std::cout << "coin coin" << std::endl;
}
};

int main( void )
{
InterfaceDuck * d = new Daffy;
d->Quack();

delete d;

return 0;
}

At the compilation, I obtain:
$ g++ -Wall test.cpp
test.cpp: In function ?int main()?:
test.cpp:21:21: error: cannot convert ?Daffy*? to ?InterfaceDuck*? in
initialization

Now, if I replace the line:
InterfaceDuck * d = new Daffy;
by:
InterfaceDuck * d = (InterfaceDuck *) new Daffy;

It compiles without warning, but it segfaults at the execution.
So, what is the correct way of doing things with pure virtual classes?

Thanks,

TP
 
A

Alain Ketterlin

TP said:
class InterfaceDuck
{
public:
virtual void Quack() = 0;
};

class Daffy

class Daffy : public InterfaceDuck
{
public:
void Quack()
{
std::cout << "coin coin" << std::endl;
}
}; [...]
$ g++ -Wall test.cpp
test.cpp: In function ?int main()?:
test.cpp:21:21: error: cannot convert ?Daffy*? to ?InterfaceDuck*? in
initialization

Inheritance must be explicit for the types to be compatible.

-- Alain.
 
T

TP

BGB wrote:

Thanks BGB for your answer,
also, IIRC, Boost may offer something like this, if this is relevant.

As I use Qt, I would like to avoid using Boost.
but, other potential strategies:

using RTTI:
merits: reasonably simple and straightforward in C++, meshes well with
C++ style, ...
downside: depends on classes and is subject to compiler issues (may be
disabled by command-line options, or require a command-line option to
enable), and may potentially have drawbacks related to overhead, on some
systems (namely Windows), it may break violently across arbitrary
borders (say, if you make a DLL and then use the DLL from an EXE, the
RTTI may not actually work).

http://en.wikipedia.org/wiki/RTTI

Reading this page, if I am right, RTTI has an interest only to know which is
the true class of an object at run time, amongst all the classes in a given
hierarchy. I am not sure it is applicable to the example I have tried to
translate (see my answer to Nobody).
If I am right, the RTTI has an interest in the frame of the "run-time
polymorphism", also called "subtype polymorphism".

http://en.wikipedia.org/wiki/Polymorphism_(computer_science)
using tagged references:
merits:
may be reasonably efficient;
very commonly used in implementing VMs (dominant strategy);
relatively C-friendly;
integers or floating point values may be directly encoded into
references (sometimes called fixnum and flonum);
...

downside:
may be more awkward to use (depending on details, requiring much added
manual boxing/unboxing/bookkeeping);
bit-twiddly and magic numbers.

I don't know what "tagged references" are. On the web, I find few websites,
and it seems it is the same as templates:

http://lambda-the-ultimate.org/node/2816

So it seems it is parametric polymorphism (see Wikipedia address above).
using "magic pointers" (where one has a raw pointer, and types are
identified based on the pointed-to object or memory-address):

merits:
can be made fairly easy to use (depending on implementation details,
dynamic types in C++ can be made to have a "look and feel" almost as if
one was them in a dynamically-typed language);
are also relatively C friendly;
generally much easier to manage than tagged references;
it is often easier to extend the type-system in an ad-hoc manner;
may be made cast-compatible with struct or class pointers;
...

downside:
potentially less efficient and more complex to implement than tagged
references;
they are a less well-known strategy;
generally, fewer bits can be afforded to fixnum and flonum types (mostly
an issue on 32-bit systems).

I don't know what "magic pointers" are, and I find few answers on the web.
Is there a link with "smart pointers"?

TP
 
D

Dombo

Op 24-Jul-11 19:55, TP schreef:
I have tried to convert the example of the webpage I mentioned:

#include<iostream>

class InterfaceDuck
{
public:
virtual void Quack() = 0;
};

class Daffy
{
public:
void Quack()
{
std::cout<< "coin coin"<< std::endl;
}
};

int main( void )
{
InterfaceDuck * d = new Daffy;
d->Quack();

delete d;

return 0;
}

At the compilation, I obtain:
$ g++ -Wall test.cpp
test.cpp: In function ?int main()?:
test.cpp:21:21: error: cannot convert ?Daffy*? to ?InterfaceDuck*? in
initialization

Now, if I replace the line:
InterfaceDuck * d = new Daffy;
by:
InterfaceDuck * d = (InterfaceDuck *) new Daffy;

It compiles without warning, but it segfaults at the execution.
So, what is the correct way of doing things with pure virtual classes?

Thanks,

You will have to derive Daffy from InterfaceDuck. Of course that way it
is no longer really duck typing, but that should be a goal in itself anyway.

If for some reason it is not practical to derive from a common base
class you might consider using templates instead:

#include <iostream>

class Donald
{
public:
void quack()
{
std::cout << "Donald: Oh, yeah?" << std::endl;
}
};

class Daffy
{
public:
void quack()
{
std::cout << "Daffy: Thatsssss dispicable!!!!" << std::endl;
}
};


template<class T>
void foo(T& duck)
{
duck.quack();
}


int main()
{
Daffy daffy;
foo(daffy);

Donald donald;
foo(donald);

return 0;
}
 
T

TP

Alain said:
class Daffy : public InterfaceDuck
Inheritance must be explicit for the types to be compatible.

In fact, I would like to have duck typing exactly as in Python: in Python
there is no need to have an inheritance relation between the interface and
the class Daffy.
In my previous post, I pointed to an example with no such inheritance
relation:

http://stackoverflow.com/questions/289176/how-is-duck-typing-different-from-
the-old-variant-type-and-or-interfaces

I would like to have a construction where the following affectation is
possible:

InterfaceDuck * d = new Daffy;

without inheritance relation between InterfaceDuck and Daffy.
The fact that Daffy has a method Quack() as InterfaceDuck should be enough
to allow that.

But perhaps there is no means to do that in C++?

TP
 
D

Dombo

Op 24-Jul-11 20:21, Dombo schreef:
Op 24-Jul-11 19:55, TP schreef:

You will have to derive Daffy from InterfaceDuck. Of course that way it
is no longer really duck typing, but that should be a goal in itself
anyway.

Corrrection: that should *not* be a goal in itself anyway.
 
D

Dombo

Op 24-Jul-11 20:23, TP schreef:
In fact, I would like to have duck typing exactly as in Python: in Python
there is no need to have an inheritance relation between the interface and
the class Daffy.
In my previous post, I pointed to an example with no such inheritance
relation:

http://stackoverflow.com/questions/289176/how-is-duck-typing-different-from-
the-old-variant-type-and-or-interfaces

I would like to have a construction where the following affectation is
possible:

InterfaceDuck * d = new Daffy;

without inheritance relation between InterfaceDuck and Daffy.

That is not possible in C++. Casting won't work be cause is Daffy isn't
a InterfaceDuck. In this case casting would be lying to your compiler,
and the compiler will have its revenge on you sooner or later for doing
that.
The fact that Daffy has a method Quack() as InterfaceDuck should be enough
to allow that.

Nope, C++ doesn't work that way. You must explicitly derive from
InterfaceDuck so the compiler knows that it is your intention that Daffy
can be used wherever InterfaceDuck is expected (i.e there is a is-a
relationship between Daffy and InterfaceDuck). That two classes merely
have a method that happens to have the same name is not good enough for
C++.
But perhaps there is no means to do that in C++?

Like I said before with templates may be able get a sort of duck typing
in C++.

However it will never be the same as in Python. The fundamental
difference between Python and C++ is that Python is a dynamically typed
language where as C++ is statically typed. This requires a different
approach and I doubt trying to write a program the Python way in C++ is
a good idea.
 
A

Alain Ketterlin

TP said:
In fact, I would like to have duck typing exactly as in Python:

You can't.
in Python there is no need to have an inheritance relation between the
interface and the class Daffy. In my previous post, I pointed to an
example with no such inheritance relation:

http://stackoverflow.com/questions/289176/how-is-duck-typing-different-from-
the-old-variant-type-and-or-interfaces

I would like to have a construction where the following affectation is
possible:

InterfaceDuck * d = new Daffy;

No way, unless InterfaceDuck and Daffy are linked by inheritance.

If you then call d->quack(), the compiler has to make sure *at compile
time* there actually is a method quack to call on d (even though it may
not be able to decide exactly which one will be called).

This is called static typing, a thing python doesn't do.

Typing is a basic programming notion, I suggest you read
http://en.wikipedia.org/wiki/Type_system

-- Alain.
 
N

Nobody

In fact, I would like to have duck typing exactly as in Python:

Then use Python.
in Python
there is no need to have an inheritance relation between the interface and
the class Daffy.

That's because Python is a dynamically-typed language, where method
look-up is done at run time.
In my previous post, I pointed to an example with no such inheritance
relation:

http://stackoverflow.com/questions/289176/how-is-duck-typing-different-from-
the-old-variant-type-and-or-interfaces

Note that the code given there isn't valid C++.
I would like to have a construction where the following affectation is
possible:

InterfaceDuck * d = new Daffy;

without inheritance relation between InterfaceDuck and Daffy.
The fact that Daffy has a method Quack() as InterfaceDuck should be enough
to allow that.

But perhaps there is no means to do that in C++?

Well, not unless you consider using C++ to write a dynamically-typed
language such as Python to be a solution.

If, for some reason, you can't make specific classes derive from
InterfaceDuck, you can use a template to create a wrapper or proxy for
such classes, e.g.:

template <class T>
class ProxyDuck : public InterfaceDuck {
T& ref;
ProxyDuck(T& ref) : ref(ref) {}
void quack() { ref.quack(); }
};
 
T

TP

Nobody said:
If, for some reason, you can't make specific classes derive from
InterfaceDuck, you can use a template to create a wrapper or proxy for
such classes, e.g.:

template <class T>
class ProxyDuck : public InterfaceDuck {
T& ref;
ProxyDuck(T& ref) : ref(ref) {}
void quack() { ref.quack(); }
};

Thanks all for your answers.

Template/proxy may be the better solution in my case (to avoid to be
compelled to do multiple inheritance in my real case).

But I have to go deeper in templates, which are still complicated to read
for me.

If I have the two solutions: (i) templating a class, or (ii) using multiple
inheritance, what is the best solution?

NOTE: if some (all?) of you understand Qt, this is my precise problem (Qt is
not the subject of this group, that's why I explain that only now): I define
a QWidget w1, which can include a QWidget w2 that must implement some
methods to be used (say: setText, readText). But if w2 is not given, w1
creates a default w2. w2 is a member of w1, in Python no type is needed for
w2, it must only provide setText and readText. But in C++, I must give a
type to w2 in the definition of w1. I could declare w1 as a template for w2.
But I could also make mandatory to have w2 to derive from an interface
(abstract class) containing setText and readText as pure virtual method; in
this case, as w2 will already derive from some Qt class, we have multiple
inheritance.
Do you understand my problem?
 
M

Marcel Müller

Come on, duck typing is a funny name for "no static typing, cross
fingers at runtime". There is no such thing in C++, which is a
statically typed, object-oriented language. This means that a call like
o.quack() in C++ will never crash at runtime with a message like "no
such method".

Well that is not true in all cases. E.g. the following code will call a
non-existent function and abort at runtime.

#include <stdio.h>

class A
{public:
virtual void foo() = 0;
A() { bar(); }
private:
void bar() { foo(); }
};

class B : public A
{public:
virtual void foo() { puts("B::foo"); }
};

int main()
{ B b;
return 0;
}


Marcel
 
T

Thomas Boell

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++?

Well you could create something where you basically stuff your function
pointers into a std::map (similar in use to a hash), then look them up
by name and call them.

This way, the compiler will not be able to tell you if you make a typo.
The call will then fail (i. e. segfault) at runtime.

If that's what you want...
 
Q

Qi

Is it possible in C++?

As other mentioned, you have two methods to do it in C++,

1, Using template. Unlike the real duck typing, the type is
solved at compile time, not at runtime.
But using template maybe hard to implement OOP hierarchy.

2, Using interface. I think this is how duck typing should
be. If an object looks like a duck, walks like a duck,
even it's not a duck, it must have duck behavior, which
is IDuck.
This is easier to implement OOP hierarchy.
 
S

Stuart Redmann

NOTE: if some (all?) of you understand Qt, this is my precise problem (Qt is
not the subject of this group, that's why I explain that only now): I define
a QWidget w1, which can include a QWidget w2 that must implement some
methods to be used (say: setText, readText). But if w2 is not given, w1
creates a default w2. w2 is a member of w1, in Python no type is needed for
w2, it must only provide setText and readText. But in C++, I must give a
type to w2 in the definition of w1. I could declare w1 as a template for w2.
But I could also make mandatory to have w2 to derive from an interface
(abstract class) containing setText and readText as pure virtual method; in
this case, as w2 will already derive from some Qt class, we have multiple
inheritance.
Do you understand my problem?

I think the template based approach should do:

template<class t_ClassTypeOfW2 = DefaultClassForW2>
class MyWidget : public QWidget
{
private:
t_ClassTypeOfW2 w2;

void foo ()
{
w2.SetText ("foo");
}
};

Now you can put any class into t_ClassTypeOfW2 as long as it has a
SetText method (no interfaces needed). However, if you would like to
determine the type of w2 at run-time (or change it), you'll have to
resort to the interface based solution.

Regards,
Stuart
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top