The Artima Developer Community
Sponsored Link

Weblogs Forum
Attempting to Define Interface Oriented Programming Languages

52 replies on 4 pages. Most recent reply: Feb 10, 2006 12:38 PM by D. Charles Lee

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 52 replies on 4 pages [ « | 1 2 3 4 | » ]
Max Lybbert

Posts: 314
Nickname: mlybbert
Registered: Apr, 2005

How C++ programmers think Posted: Dec 28, 2005 1:01 PM
Reply to this message Reply
Advertisement
C++ Programmers have to decide to make methods "virtual" in order to allow OOP practices. They know that doing so has a performance penalty, but can make their lives much easier. Java, BTW, just takes the performance hit all the time unless you say a method is "final."

An explanation of why there's a speed hit can be found at Wikipedia at http://en.wikipedia.org/wiki/Virtual_table (and, yes, I know that CDiggins doesn't like Wikipedia, this article is a good reason not to, more details soon).

When a class doesn't need a vtable, C++ doesn't provide one. The alternative *isn't* a compiled-in pointer as referred to in the article, but rather a name-mangled function that gets called directly. That is, assembly code has no idea what a class is, but there are functions in assembly code. C++ fakes classes by creating a structure that holds all the data, and then defining all methods as functions that take that structure as a hidden argument. This happens behind the scenes, and only your debugger knows about it. The point is OOP methods go through a pointer, and regular methods don't. Going through a pointer is slower than not doing so -- hence the speed hit.

The fact that CDiggins has defined the interfaces concept as something resolved at compile time means that the methods in question would be compiled down to name-mangled function without a pointer involved. No speed hit.

The sticky problem is making sure enough information is around at compile time to resolve the interface question.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: How C++ programmers think Posted: Dec 28, 2005 1:47 PM
Reply to this message Reply
> C++ Programmers have to decide to make methods "virtual"
> in order to allow OOP practices.

Yes, I've always consider this to be more of a flaw than a feature.

> They know that doing so
> has a performance penalty, but can make their lives much
> easier. Java, BTW, just takes the performance hit all the
> time unless you say a method is "final."

Not for static methods. Static methods are always non-virtual.

The question I have is that if you don't want the method to be associated with the Object but rather the class it is defined in, why not just make it part of the class (other than the convienience of not having to specify the Object as a parameter to the method)?

> An explanation of why there's a speed hit can be found at
> Wikipedia at http://en.wikipedia.org/wiki/Virtual_table
> (and, yes, I know that CDiggins doesn't like Wikipedia,
> this article is a good reason not to, more details soon).
>
> When a class doesn't need a vtable, C++ doesn't provide
> one. The alternative *isn't* a compiled-in pointer as
> referred to in the article, but rather a name-mangled
> function that gets called directly. That is, assembly
> code has no idea what a class is, but there are functions
> in assembly code. C++ fakes classes by creating a
> structure that holds all the data, and then defining all
> methods as functions that take that structure as a hidden
> argument.

As I understand it, Java does essentially the same thing.

> This happens behind the scenes, and only your
> debugger knows about it. The point is OOP methods go
> through a pointer, and regular methods don't. Going
> through a pointer is slower than not doing so -- hence the
> speed hit.

My understanding was that determining version of the method to call based on the type of the Object was what takes a long time. I'm not convinced 'going through a pointer' is slow. In fact, passing an address to a method is often going to be faster than copying all the data in the Object from one area of memory to another.

> The fact that CDiggins has defined the interfaces concept
> as something resolved at compile time means that the
> methods in question would be compiled down to name-mangled
> function without a pointer involved. No speed hit.

I've not been following CDs language closely but Heron supports pass-by-value semantics, there will always be a pointer involved. In any event I didn't get the idea that using this technique would change anything about whether the references were pointers, just that the method binding would be done at compile time.

Max Lybbert

Posts: 314
Nickname: mlybbert
Registered: Apr, 2005

Re: How C++ programmers think Posted: Dec 28, 2005 1:50 PM
Reply to this message Reply
Rethinking this, I have to admit Wikipedia is right.

C++ programmers generally think of compiling down to C code, but not to assembly code, let alone true machine code.

Assembly code generally doesn't have a standard function call mechanism. That's the point of stdcall.

Stdcall is the slangy term for C's function calling convention, that effectively involves a stack-based way of passing arguments and a compiled-in pointer. So Wikipedia is correct that there is a pointer involved. Then again, with a vtable, there is an extra pointer involved, which creates the speed hit.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: How C++ programmers think Posted: Dec 28, 2005 1:53 PM
Reply to this message Reply
> Java, BTW, just takes the performance hit all the
> time unless you say a method is "final."

Actually, this isn't totally correct. It's possible that final methods could be optimized at runtime by a JIT compiler but there is nothing in the JLS that specifies that a java compiler should do this for final methods. It could cause unexpected behavior if the final was removed and all classes that used it were not recompiled similar to what happens when literals are inlined.

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: How C++ programmers think Posted: Dec 28, 2005 1:55 PM
Reply to this message Reply
> Rethinking this, I have to admit Wikipedia is right.
>
> C++ programmers generally think of compiling down to C
> code, but not to assembly code, let alone true machine
> code.
>
> Assembly code generally doesn't have a standard function
> call mechanism. That's the point of stdcall.
>
> Stdcall is the slangy term for C's function calling
> convention, that effectively involves a stack-based way of
> passing arguments and a compiled-in pointer. So Wikipedia
> is correct that there is a pointer involved. Then again,
> with a vtable, there is an extra pointer involved, which
> creates the speed hit.

Another factor affecting performance of virtual functions is that because the dispatch occurs at runtime, it can't be inlined at compile time, which is a very important optimization.

Drew McCormack

Posts: 3
Nickname: cormack
Registered: Dec, 2005

Re: Attempting to Define Interface Oriented Programming Languages Posted: Dec 28, 2005 2:26 PM
Reply to this message Reply
> > You can always implement IOP in an OO
> > language by introducing interface classes, so I would
> > argue that IOP is just a specialized case of OOP.
>
> In C++ however you can't implement interfaces without
> using virtual functions, or some really ardurous table
> initialization code. The idea of an IOP, is to be able to
> use objects polymorphically without virtual functions.

But you can't avoid dynamic lookup, can you? I assume if you assign an object to an interface type at run time, it must incur the same performance hit as a virtual function, or am I missing something?

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Attempting to Define Interface Oriented Programming Languages Posted: Dec 28, 2005 2:53 PM
Reply to this message Reply
> But you can't avoid dynamic lookup, can you? I assume if
> you assign an object to an interface type at run time, it
> must incur the same performance hit as a virtual function,
> or am I missing something?

If I understand the difference would be like the difference between how static methods and object methods are treated in Java.
class Foo
{
    void bar()
    {
        System.out.println("I am a Foo");
    }
 
    void classBar()
    {
        System.out.println("I am a Foo");
    }
}
 
class SubFoo
{
    void bar()
    {
        System.out.println("I am a SubFoo");
    }
 
    void classBar()
    {
        System.out.println("I am a SubFoo");
    }
}
 
//...
 
{
    Foo foo = new SubFoo();
 
    foo.bar(); // "I am a SubFoo"
    foo.classBar(); // I am a Foo
    ((SubFoo) foo).bar(); // "I am a SubFoo"
    ((SubFoo) foo).classBar(); // "I am a SubFoo"
}


I nthe above, the calls to the static methods are bound at compile-time. The compiler can do this because it has everything it needs to know at compile-time.

I believe that CD is contemplating allowing the above to be done on object methods, though it is not clear whether this determination is made by the class specification or by the caller.

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Attempting to Define Interface Oriented Programming Languages Posted: Dec 28, 2005 3:49 PM
Reply to this message Reply
> > > You can always implement IOP in an OO
> > > language by introducing interface classes, so I would
> > > argue that IOP is just a specialized case of OOP.
> >
> > In C++ however you can't implement interfaces without
> > using virtual functions, or some really ardurous table
> > initialization code. The idea of an IOP, is to be able
> to
> > use objects polymorphically without virtual functions.
>
> But you can't avoid dynamic lookup, can you? I assume if
> you assign an object to an interface type at run time, it
> must incur the same performance hit as a virtual function,

Yes. But the function isn't always going to be used virtually.

For example in C++:


struct Pet {
virtual get_sound() = 0;
};

struct Cat : Pet {
void output_sound() {
// this call to get_sound can not be inlined
// get_sound() might be overridden in a derived class
cout << get_sound();
}
string get_sound() {
return "meow";
}
};

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Attempting to Define Interface Oriented Programming Languages Posted: Dec 28, 2005 3:50 PM
Reply to this message Reply
Sorry, the example should read:

class Foo
{
    void bar()
    {
        System.out.println("I am a Foo");
    }
 
    static void classBar()
    {
        System.out.println("I am a Foo");
    }
}
 
class SubFoo
{
    void bar()
    {
        System.out.println("I am a SubFoo");
    }
 
    static void classBar()
    {
        System.out.println("I am a SubFoo");
    }
}

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Attempting to Define Interface Oriented Programming Languages Posted: Dec 28, 2005 3:55 PM
Reply to this message Reply
> If I understand the difference would be like the
> difference between how static methods and object methods
> are treated in Java.

I am not sure I follow, but I wouldn't make that comparison. I am trying to say that in an IOPL, the only method of dynamic dispatching would be through interface references, thus eliminating the need for virtual and abstract functions.

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Attempting to Define Interface Oriented Programming Languages Posted: Dec 28, 2005 6:42 PM
Reply to this message Reply
For those interested, I just posted a description of the latest HeronFront (which I also posted) at http://www.heron-language.com/heronfront.html . It goes into more detail than my blog entry, and hopefully is more clear.

I appreciate everyone's feedback, it is helping me hone my message.

Tim LS

Posts: 37
Nickname: parchandri
Registered: Jul, 2005

Re: Attempting to Define Interface Oriented Programming Languages Posted: Dec 28, 2005 11:15 PM
Reply to this message Reply

interface Pet {
signature {
string make_sound();
}
};

class Cat {
public:
string make_sound() {
return "meow";
}
};

class Dog {
public:
string make_sound() {
return "woof";
}
};


I got a bit confused by this statement in the original post:

>a class will always the same behaviour, no matter how it is inherited

With the Pet example: the interface is no more detailed than a Java interface. That is, it specifies a method signature only (string make_sound()). There are no semantic checks. Even though they implement the appopriate method, the behaviour of Dog and Cat objects is slightly different - one makes "meow", the other makes "woof". Now as far as the interface definition goes, both classes have behaviour meeting the definition, and in that respect they are identical. If the interface could specify other details, e.g. sound cannot be "", then the compiler could perhaps also check for those (but there are decidability problems).

Now, with subclassing, we could create a class Pet, and subclass it to class Dog. And by default the Dog would have the same make_sound behaviour as a Pet. Exactly the same. But you can change behaviour, by overriding the method, as long as you don't change the method specification.

Now because the behaviour could be different, that allows a substitutability violation. e.g. you can substitute a Dog for a Pet, because it is a subclass of Pet, but if the behaviour of the Dog is not matching what is expected of the Pet, the program can produce garbage results.

Using the interface oriented system instead, does this mean that there is no inheritance allowed? And that substitutability comes from a class matching the interface only? And so all functions must be reimplemented in new classes? Or only that we may not use abstract (unimplemented functions) in base classes?

But, I think that was all a bit of a tangent to what you were talking about.

So: Is the only drawback of the old inheritance mechanism that you have to use virtual function call mechanism? Is that the only problem IOP wishes to fix? That barely sounds like enough for a new language, let alone a new language class.

It sounds like a less expressive language than C++; the same, except that you are not allowed to declare partially abstract classes, only purely abstract ones. Whereas people could instead be choosing to use that subset of C++, and allow the compilers to optimize smartly.

Gregor Zeitlinger

Posts: 108
Nickname: gregor
Registered: Aug, 2005

Re: Attempting to Define Interface Oriented Programming Languages Posted: Dec 29, 2005 2:05 AM
Reply to this message Reply
> > If I understand the difference would be like the
> > difference between how static methods and object
> methods
> > are treated in Java.
>
> I am not sure I follow, but I wouldn't make that
> comparison. I am trying to say that in an IOPL, the only
> method of dynamic dispatching would be through interface
> references, thus eliminating the need for virtual and
> abstract functions.
I think I finally understand.

Continuing the above example:
interface Foo
{
    void bar();
}
 
class SubFoo implements Foo
{
    void bar()
    {
        System.out.println("I am a SubFoo");
    }
}
 
class BrokenFoo extends SubFoo
{
    void bar() {} //does not compile, bar is not virtual
}
 
Foo foo = new SubFoo();
 
// "I am a SubFoo", dynamic resolution (vtable lookup)
foo.bar(); 
 
// "I am a SubFoo", static resolution (may be inlined)
((SubFoo) foo).bar(); 
 

Terje Slettebø

Posts: 205
Nickname: tslettebo
Registered: Jun, 2004

Re: How C++ programmers think Posted: Dec 29, 2005 6:28 AM
Reply to this message Reply
> C++ Programmers have to decide to make methods "virtual"
> in order to allow OOP practices. They know that doing so
> has a performance penalty

Not necessarily. Whether or not a call is resolved at compile-time or run-time is an implementation detail, but if not enough information (for that specific compiler) is available at compile-time to make the decision, then it will be resolved at run-time. To take en example:

void f(Derived d)
{
d.g();
}

Here, even if g() is defined to be virtual, the call will be resolved at compile-time, and g() will be called non-virtually, possibly inlined. That's because the compiler knows the type of "d".

However, if "d" is a pointer or reference to Base, and the compiler can't otherwise figure out what its "dynamic type" (the type of the object being referenced or pointed at) is, then the call will be resolved dynamically:

void f(Derived &d)
{
d.g();
}

In the first example, it might even elide the vtable-pointer in the object in f(), as it doesn't need it to make the call, hence the virtual function declaration not having any size-implications of the object, either. Again, it is implementation-defined whether or not that happens.

> C++ fakes classes by creating a
> structure that holds all the data, and then defining all
> methods as functions that take that structure as a hidden
> argument.

That's a puzzling way of putting it, and strictly speaking, wrong. What you describe is _one_ possible way of implementing classes in C++ (as well as other languages with a similar OO-model, like Java), but not the only one. It's, however, probably more or less the only method being used, as it works well. However, my point is that nowhere in the C++ standard does it specify how classes and virtual functions are implemented.

Secondly, could you explain what you mean by this implementation method being used to "fake classes"? In this case, how do you define "real" classes, and can you provide any "authority" as to what should be the proper definition of "class"? (The earliest use of classes, is, from what I've hard, the Simula language in the 60's. Both Smalltalk and C++ "inherited" the notion of classes and polymorphism from Simula.)

> The fact that CDiggins has defined the interfaces concept
> as something resolved at compile time means that the
> methods in question would be compiled down to name-mangled
> function without a pointer involved. No speed hit.

Just as a compiler can do if it has enough knowledge to resolve the call to a virtual function at compile-time, as shown above.

> The sticky problem is making sure enough information is
> around at compile time to resolve the interface question.

Indeed, and you may not even have that information at that time. However, a design that dispatches at compile-time when it can, and at run-time otherwise, and doesn't require inheritance from a common base class or interface, is an interesting idea, and would nicely fuse a mechanism like C++ templates and inheritance-based polymorphism (inclusion polymorphism), giving the "duck typing" of templates at run-time, without requiring dynamically typed variables (as in script languages). As I understood from an earlier posting by Christopher in another thread, Heron either had, or might have such a feature.

Regards,

Terje

Terje Slettebø

Posts: 205
Nickname: tslettebo
Registered: Jun, 2004

Re: How C++ programmers think Posted: Dec 29, 2005 6:29 AM
Reply to this message Reply
> > C++ Programmers have to decide to make methods
> "virtual"
> > in order to allow OOP practices.
>
> Yes, I've always consider this to be more of a flaw than a
> feature.

There exists different opinions on this matter. :) (Java makes you make the same choice - final or not final, but the default is the opposite of C++) It would be nice if we didn't have to - in advance - specify something as virtual or non-virtual, and instead have the compiler figure it out, but the problem is that the full knowledge for doing this is only available at link time, and many environments allow dynamical linking at run-time.

Whether something is a feature or a flaw, should be determined based on the design goals of the language (then one may instead judge _them_, based on what they aim at, or what one wants), and based on C++'s design goals - which included not paying for what you don't use, as well as compatibility with C, I think it may be argued that a non-virtual default is a reasonable choice, and not a flaw, considering the goals.

Regards,

Terje

Flat View: This topic has 52 replies on 4 pages [ « | 1  2  3  4 | » ]
Topic: The Joy of Joy Previous Topic   Next Topic Topic: Audio Interview

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use