Thursday, January 28, 2016

Digest for comp.lang.c++@googlegroups.com - 25 updates in 3 topics

JiiPee <no@notvalid.com>: Jan 28 11:21AM

How do you organieze code in your project in regarding to a number of
files you have?
Lets say you have 20-30 different options in menu to do something which
each take more than 50 lines of code. Woud you separate them
to different files or put then on a same file? Is it a good idea to have
a lot of smaller files in a project of combine them?
 
I guess its faster to compile if there are a lot of small files as only
that file needs to be compiled if changed?
scott@slp53.sl.home (Scott Lurndal): Jan 28 02:19PM

>a lot of smaller files in a project of combine them?
 
>I guess its faster to compile if there are a lot of small files as only
>that file needs to be compiled if changed?
 
Generally, I have one header file and one source file per class.
 
Sometimes there is need for a private header file in addition to the
public header file, but that's rare and usually due to circular include
issues in larger projects.
JiiPee <no@notvalid.com>: Jan 28 04:11PM

On 28/01/2016 14:19, Scott Lurndal wrote:
 
>> I guess its faster to compile if there are a lot of small files as only
>> that file needs to be compiled if changed?
> Generally, I have one header file and one source file per class.
 
Even if the classes are small and there are a lot of classes? say you
have 30 small classes, would you still put them to a separate files?
Victor Bazarov <v.bazarov@comcast.invalid>: Jan 28 11:18AM -0500

On 1/28/2016 11:11 AM, JiiPee wrote:
>> Generally, I have one header file and one source file per class.
 
> Even if the classes are small and there are a lot of classes? say you
> have 30 small classes, would you still put them to a separate files?
 
You call 30 "a lot"?
 
V
--
I do not respond to top-posted replies, please don't ask
Wouter van Ooijen <wouter@voti.nl>: Jan 28 05:26PM +0100

Op 28-Jan-16 om 12:21 PM schreef JiiPee:
> a lot of smaller files in a project of combine them?
 
> I guess its faster to compile if there are a lot of small files as only
> that file needs to be compiled if changed?
 
When compilation time is a real problem that is a good argument for
organizing your code. But that argument might actually favour mid-sized
source files: on one side too many small files means too many runs of
the compiler when a common header is changed, and on the other side too
large a file(s) causes the whole file to be re-compiled when only a
small part is changed. It is a balance....
 
But when compilation time is NOT an issue, I would favour readability
over anything else. But that again might depend on context. I like
related classes to be in one file (I like to print and read while taking
a bath), others might like to find the source fo a class in a file with
teh same name. Yet others couldn't care either way because their IDE
will find a class definition for them....
 
Find out what works for you!
 
Wouter van Ooijen
Paavo Helde <myfirstname@osa.pri.ee>: Jan 28 06:32PM +0200

On 28.01.2016 18:11, JiiPee wrote:
>> Generally, I have one header file and one source file per class.
 
> Even if the classes are small and there are a lot of classes? say you
> have 30 small classes, would you still put them to a separate files?
 
If I have small helper classes which only make sense when used together
with a certain larger class, then I generally put them in the same .h
and .cpp files with the larger class.
 
It is true that recompiling a single small file is faster than
recompiling a single large file. However, recompiling a lot of small
files can be significantly slower than recompiling a couple of large
files (especially if precompiled header support is not working well for
any reason).
scott@slp53.sl.home (Scott Lurndal): Jan 28 04:38PM

>> Generally, I have one header file and one source file per class.
 
>Even if the classes are small and there are a lot of classes? say you
>have 30 small classes, would you still put them to a separate files?
 
$ ls */*.h |wc -l
161
 
About 10 of these aren't class definitions, the rest are.
scott@slp53.sl.home (Scott Lurndal): Jan 28 04:43PM

>files can be significantly slower than recompiling a couple of large
>files (especially if precompiled header support is not working well for
>any reason).
 
On any modern system, it's not really significantly slower (at least on linux and
unix systems) because the common header files will end up cached in memory after
the first couple of compiles.
 
It may really suck on windows, but I've been able to successfully avoid
using windows[*] since it was introduced in 1985 (10 years after I started programming).
 
[*] Except for writing a couple of device drivers for NT 3.51 (Optical-WORM and associated
Jukebox drivers) in the 90's.
"Öö Tiib" <ootiib@hot.ee>: Jan 28 08:44AM -0800

On Thursday, 28 January 2016 18:12:02 UTC+2, JiiPee wrote:
> > Generally, I have one header file and one source file per class.
 
> Even if the classes are small and there are a lot of classes? say you
> have 30 small classes, would you still put them to a separate files?
 
30 classes is perhaps a tiny toy tool for trying out something.
Often there are 100-200 classes even in relatively dumb embedded
software.
 
To split things up into several files is especially good idea on cases like
you described that these are some sort of GUI widgets. GUI changes are
most likely and most frequent during development. It is major pain and
lot of wasted work time when 11 persons edit one large *.rc file for
Windows app that they develop and then try to merge the changes.
4ndre4 <4ndre4@4ndre4.com.invalid>: Jan 28 12:35AM

On 27/01/2016 21:14, Christopher Pisz wrote:
 
> I agree 100% the diamond problem is a problem, but I can just as easily
> adapt the "An interface does not contain functionality or data" and then
> the diamond problem is no longer a problem, right?
 
Actually, to avoid the diamond problem, you can just resort to virtual
inheritance. You do not necessarily need to make the base class at the
top of the diamond the equivalent of a C# interface.
 
You can have this:
 
#include <iostream>
 
class Storable {
public:
virtual void read() {
std::cout << "storable reading" << std::endl;
};
virtual void write() {
std::cout << "storable writing" << std::endl;
};
};
 
class Receiver : public virtual Storable {
public:
void read() {
std::cout << "receiver reading" << std::endl;
}
};
 
class Transmitter : public virtual Storable {
public:
void write() {
std::cout << "transmitter writing" << std::endl;
}
};
 
class Radio: public Receiver, Transmitter {
public:
void read() {
std::cout << "radio reading" << std::endl;
}
void write() {
std::cout << "radio writing" << std::endl;
}
};
 
int main()
{
Storable* p = new Radio();
p->read();
p->write();
 
p = new Receiver();
p->read();
p->write();
 
p = new Transmitter();
p->read();
p->write();
 
return 0;
}
 
 
The output is, as expected:
 
radio reading
radio writing
receiver reading
storable writing
storable reading
transmitter writing
 
Of course, if you remove "virtual" from the intermediate base classes,
you'll get the diamond ambiguity back, with the compiler stopping with a
fatal error.
 
--
4ndre4
"The use of COBOL cripples the mind; its teaching should, therefore, be
regarded as a criminal offense." (E. Dijkstra)
Marcel Mueller <news.5.maazl@spamgourmet.org>: Jan 28 03:36AM +0100

On 27.01.16 21.16, Christopher Pisz wrote:
> Premise: Multiple inheritance is universally accepted as bad
 
Wrong.
 
There are problems that are really hard to solve without multiple
inheritance. At least it breaks the "don't repeat yourself" rule.
 
Example:
Think of an entity data model. Each entity has a immutable, inherently
thread-safe representation and a mutable representation. Of course, any
code that works with the read only (maybe cached) entities is supposed
to work also with local mutable instances rather than the shared
immutable ones. It is up to the caching framework to deliver either
type. But you can always enforce a mutable copy, if you intend to make
changes.
It is straight forward to solve this by inheritance. The mutable classes
inherit from the immutable ones add some further methods.
 
Additionally there are strong entities (with a strong key), weak
entities (i.e. children of strong entities with sub keys) and simple
entities without any key. This is also straight forward to be serviced
with inheritance. Whatever you can do with a simple entity can be done
with weak or strong entities as well.
 
Now you have multiple inheritance.
A strong mutable entity inherits from the simple entity as well as from
the strong immutable entity. You need both implicit conversions to make
all code work.
 
I had to implement something like that in C# and it really wasn't fun
because of the lack of multiple inheritance.
 
Another example:
Think of a logger API. You may have a FileLogger class and e.g. a
DailyFileLogger class that inherits from the first and added
functionality for logfile rotation.
For performance reasons there are multi-tasking safe implementations
that synchronize write access to the file (even over the network) and
single task implementations that simply keep the file open in exclusive
write mode. Any application that can deal with the local implementation
is supposed to work with the synchronized classes as well.
Again you have multiple inheritance.
 
 
> Conclusion: Although the compiler allows you to, you should never use
> multiple inheritance in C++
 
Well, if you do not know what you are doing then you should avoid
multiple inheritance. Otherwise it might be very useful in some cases.
Of course, like any other pattern one should not abuse it.
 
It is like multiple dispatch. If you really need it, code becomes really
ugly if the language (like C++) does not support it.
 
 
Marcel
Rosario19 <Ros@invalid.invalid>: Jan 28 06:35AM +0100

On Wed, 27 Jan 2016 14:16:23 -0600, Christopher Pisz wrote:
 
>is making some bold sweeping claims about C++ and C#, which I have to
>disagree with. It's lighthearted and for fun. I wonder what others say
>on the topic.
 
i never had find a problem where it is need "virtual" until now
Zaphod Beeblebrox <a.laforgia@gmail.com>: Jan 28 01:57AM -0800

On Thursday, 28 January 2016 02:36:39 UTC, Marcel Mueller wrote:
 
> There are problems that are really hard to solve without multiple
> inheritance.
 
I am suspecting that for the problems you are presenting, composition is a better choice than inheritance/MI. Maybe I got it wrong. Can you offer some code examples?
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jan 28 11:57AM +0100

On 1/27/2016 11:12 PM, Mr Flibble wrote:
>> implementation of an interface, one must use virtual inheritance.
 
> Why would you want to emulate Java/C# inheritance in C++? If you are
> using C++ then use C++.
 
Yeah, I mostly agree.
 
Still there's a school of thought that one should always inherit
virtually from an interface (pure abstract class). The Java-like
"inherit in an implementation" is one possible reason, because, as an
example, it comes into play when you have an interface A, an
implementation of A called say A_impl, plus an interface that extends A,
say B, and you want to provide the extended interface B with the A_impl
implementation of the A part. And another possible reason is to ensure
that direct casting up to some given interface is unambiguous, e.g. for
catching an exception as reference to that interface.
 
Still, there are workarounds for those issues, I think that doing
exception discrimination via interfaces is complexity for no gain, and
while virtual inheritance of an interface doesn't confront you with the
special construction order for virtual base classes (which sort of
stinks) there is a run time cost of extra indirection (which itches).
 
 
Cheers!,
 
- Alf
 
Disclaimer: no coffee yet, just out of bed.
JiiPee <no@notvalid.com>: Jan 28 11:38AM

On 28/01/2016 00:35, 4ndre4 wrote:
> p->write();
 
> return 0;
> }
 
beautifully written code. :) easy to read...
Zaphod Beeblebrox <a.laforgia@gmail.com>: Jan 28 05:27AM -0800

On Thursday, 28 January 2016 11:38:58 UTC, JiiPee wrote:
 
[...]
> beautifully written code. :) easy to read...
 
A code that doesn't do anything is always easy to read :D
scott@slp53.sl.home (Scott Lurndal): Jan 28 02:16PM

>> Conclusion: Although the compiler allows you to, you should never use
>> multiple inheritance in C++
 
>I've used it exactly once.
 
I use it often, for example:
 
/**
* Reset block
*/
class Reset: public Device,
public MemoryAccessors,
GpioPinCb,
public Thread
{
};
 
MemoryAccessors and GpioPinCb are both pure virtual classes (interfaces).
Thread and Device are base classes.
 
A pointer to the instance as 'MemoryAccessors *' is kept in the
object that manages the physical address space, and a pointer to
the instance as 'GpioPinCb *' is kept in the GPIO device object
instance. A pointer to the instance as 'Device *' is kept in the
master device vector, and a pointer to the instance as 'Thread *'
is kept by the thread manager singleton.
Rosario19 <Ros@invalid.invalid>: Jan 28 06:25AM +0100

On Wed, 27 Jan 2016 20:09:52 +0000, Mr Flibble wrote:
>incorrect: it should probably be std::size_t.
 
>/Flibble
 
>P.S. Sausages.
 
use unsigned type of fixed size
because
1) assembly programmers use unsigned fixed size registers
2) they would have 0 UBs
3) are easier to handle and write ok
4) because i always like unsigned until i see them
and not use int, and i not find hard problems with them
"Öö Tiib" <ootiib@hot.ee>: Jan 27 11:57PM -0800

On Wednesday, 27 January 2016 23:50:19 UTC+2, Mr Flibble wrote:
> > iii) sausages
 
> ii) and iii) are in conflict as you cannot eat a negative number of
> sausages.
 
The 'argc' of 'main' can also never be negative but that does not make
it unsigned value. It is signed value whose sign is always positive.
leigh.v.johnston@googlemail.com: Jan 28 01:10AM -0800

argc is an artifact of ancient lazier times: if we were to reinvent main today we would do it differently.
leigh.v.johnston@googlemail.com: Jan 28 01:10AM -0800

argc is an artifact of ancient lazier times: if we were to reinvent main today we would do it differently.
leigh.v.johnston@googlemail.com: Jan 28 01:10AM -0800

argc is an artifact of ancient lazier times: if we were to reinvent main today we would do it differently.
Ian Collins <ian-news@hotmail.com>: Jan 28 10:17PM +1300

> argc is an artifact of ancient lazier times: if we were to reinvent
> main today we would do it differently.
 
Three times differently :)
 
Too many sausages?
 
--
Ian Collins
leigh.v.johnston@googlemail.com: Jan 28 02:41AM -0800

On Thursday, January 28, 2016 at 9:17:55 AM UTC, Ian Collins wrote:
> > main today we would do it differently.
 
> Three times differently :)
 
> Too many sausages?
 
No, it's bloody Google Groups and Google Chrome...
 
/Leigh
Bo Persson <bop@gmb.dk>: Jan 28 02:24PM +0100

On 2016-01-27 22:50, Mr Flibble wrote:
 
> ii) and iii) are in conflict as you cannot eat a negative number of
> sausages.
 
> /Flibble
 
What about
 
unsigned yesterdays_sausages = 6;
unsigned todays_sausages = 5;
 
unsigned difference = todays_sausages - yesterdays_sausages;
 
 
Doesn't really work, does it?
 
 
 
Bo Persson
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: