- Putting project code in many different files - 9 Updates
- Let's talk about multiple inheritance and interfaces. - 8 Updates
- 'int' considered dangerous (reprise) - 8 Updates
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:
Post a Comment