[linux-audio-dev] (OT) C++ flame war

Paul Davis paul at linuxaudiosystems.com
Thu Feb 6 12:01:00 UTC 2003


>[...]
>> i love C++. i think its one of the best things ever. but i happen to
>> agree with Erik. the solution proposed by martijn doesn't scale well,
>> and doesn't really address the issue in a comprehensive way. it
>> requires one pure virtual class per distinct set of private members,
>> for a start.
>
>No, it requires a pure virtual class per distinct interface (abstract
>class). And I don't see why this would not scale.

you should try writing ardour :)

>A friend is just like a member function, i.e. it can access the
>class' private data, but it is not in the class' scope and the
>function is not invoked on

i know what a friend *is* - i was trying to convey what i want a
friend to be in the best of all possible worlds.

>When possible other  classes should interact using a class' public
>interface(s).

the point is that i want semi-public interfaces that are not
implemented via abstract classes or inheritance because they cover
functionality that is still tightly coupled to the rest of the object.
by making them abstract, i can solve the coupling at the
implementation level (because the implementation only exists in the
concrete classes). but i still find this really messy.

conceptually, i am not creating a distinct type of object - i want to
provide a particular set of objects with access to a limited set of
member functions belonging to an otherwise unified object. C++ won't
let me do that - it forces me to use an abstract class, multiple
inheritance and virtual functions to get the job done. being able to
limit the scope of a friend declaration would solve this problem in a
much more natural way, i think.

>class A { // some interface
>public:
>    virtual void a() = 0;
>};
>
>class B { // another interface
>public:
>    virtual void b() = 0;
>};
>
>class editor : public A, public B { // the editor provides both interfaces
>public:
>    void a();
>    void b();
>};
>
>and now a class C that wants to use the functionality of the editor that is
>exported by interface A can use it like:
>
>void f(A& i) {
>    i.a();
>}
>
>without depending on the implementation.

this is precisely the solution i find so cumbersome. an editor is not
an A, and a B and a C and a D. its an editor. the point is that only
certain other things should be able to call a() and other things
should be the only ones to call b(). its very unnatural to declare
this in this way, although yes, i know that it works.

>Correct. But perhaps you are misusing the friend concept. Are these
>friend classes so closely related that they cannot use some public
>interface?

as i said above, the interfaces are not public. they are intended to
be restricted just to the specified other classes.

>> none of this helps with the problem erik identified.
>
>The problem Erik identified was that one could not seperate the
>interface from the implementation in C++. I then said this can be
>done using an abstract class, i.e. an interface.

i would accept that this is true for relatively simply objects. i just
don't think it scales well. the current ardour editor has about 7000
lines of code, the object itself has about 800 members (either data or
functions). splitting this up is a non-trivial exercise.

nevertheless, it could truly be worth doing. the compilation
dependencies right now are horrendous. changing editor.h requires me
to wait about 10 minutes for a recompile :)

>> i would really
>> love a C++ that did this:
>>
>>      class Foo {
>>         public:
>> ... stuff ...
>>         private:
>>        <some tokens that meant something like #include>
>>      };
>>
>> and then in other files, you would do:
>>
>>     #use "foo.h"
>>
>> or
>>
>>     #implementation "foo.h"
>>
>> or something like that. the first one would just bring in the public
>> declarations, and its what you'd use when you're calling or creating
>> Foo objects. the second one would be used in the definitions for the
>> member functions of Foo, and hence would almost certainly be limited
>> to "foo.cc".
>
>It doesn't work that way. You cannot create an class instance without
>its full declaration. I don't see the problem of having the private part

i don't believe that this is true. the actual code executed by
constructor is the only thing that needs to know the full
declaration. the one exception is creating objects on the heap, where
we need a size so that we can allocate memory, and then run the
constructor using the returned address. i'd be happy with a language
where

	x = new Foo;

really translates to:

       x = Foo::constructor (malloc (Foo::sizeof());

where ::sizeof() is a built-in compiler-generated virtual.

>> note that the private stuff would be in a file that looked just like
>> the class declaration, but had no public (and protected?)
>> declarations. in other words, the class declaration it includes is
>> implicitly 100% private, but it can include header files that are
>> necessary for the private declarations.
>
>I don't see what this would solve and I don't think this is even possible.
>Changing the private part will break binary compatibility (without
>changing the public header).

the dependency part is easily solved by the compile system. given the
new preprocessor directives it would require anyway, you'd just
generate dependencies that included the private part. then if the
private part changes, even though its never read by the users of the
public interface, they are recompiled too.

anyway, its water under the bridge. C++ doesn't do this, and will
likely never do this.

--p






More information about the Linux-audio-dev mailing list