Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
FearIt
Mar 11, 2007

JoeNotCharles posted:

Have you tried Googling "CreateProcess example"?
Yeah, I've googled it and the examples I'm getting I'm just not sure how to utilize. Im trying to convert some VB code which was as simple as shell("c:\myprog.exe") and am having trouble with the windows programming part.

I'm trying to do this without .net if possible.

Adbot
ADBOT LOVES YOU

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
There are examples down at the bottom of the MSDN page: http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe

FearIt posted:

I'm having trouble understanding all the arguements is there anyway I could get an example of CreateProcess?

It's pretty simple actually.

code:
#include <windows.h>

char target[] = "\\test.exe";
char path[MAX_PATH];
STARTUPINFO         si = { 0 };
PROCESS_INFORMATION pi;

int main(){
	si.cb = sizeof(STARTUPINFO);
	GetCurrentDirectory((MAX_PATH - sizeof(target)), (LPSTR)&path);
	lstrcat((LPSTR)&path, (LPSTR)&target);
	CreateProcess((LPSTR)&path, NULL, NULL, NULL, FALSE, 
				  NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
}
edit: I like how my pi turned into an actual PI... at least that's what I think it did? wtf.

more falafel please
Feb 26, 2005

forums poster

slovach posted:

It's pretty simple actually.

code:
#include <windows.h>

char target[] = "\\test.exe";
char path[MAX_PATH];
STARTUPINFO         si = { 0 };
PROCESS_INFORMATION pi;

int main(){
	si.cb = sizeof(STARTUPINFO);
	GetCurrentDirectory((MAX_PATH - sizeof(target)), (LPSTR)&path);
	lstrcat((LPSTR)&path, (LPSTR)&target);
	CreateProcess((LPSTR)&path, NULL, NULL, NULL, FALSE, 
				  NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
}
edit: I like how my pi turned into an actual PI... at least that's what I think it did? wtf.

Looks like at least some browsers (Safari at least) treat & p i ) ; as & p i ;, which should render as the pi symbol.

TSDK
Nov 24, 2003

I got a wooden uploading this one
Here's a dirt-simple process wrapper app I did a while ago. We used it to launch windowed apps from a batch file (as part of an automated asset building process) so that the batch file would wait until the app had closed down before carrying on.
code:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <string>

int main( int argc, char *argv[] )
{
    // Make sure we have enough paramaters
    if ( argc < 2 )
    {
        printf( "ERROR: Not enough arguments\n" );
        printf( "USAGE: %s <process_name> <optional_arguments>\n", argv[0] );
    }

    // Get the process arguments
    std::string command_line;
    for ( int i = 1; i < argc; i++ ) // Include the module name in the command line
    {
        std::string argument( argv[i] );
        if ( argument.find( ' ' ) == std::string::npos )
        {
            command_line += argument + std::string( " " );
        }
        else
        {
            command_line += std::string( "\"" ) + argument + std::string( "\" " );
        }
    }
    char *p_argument_buffer = new char[command_line.size()];
    memset( p_argument_buffer, 0, command_line.size() );
    memcpy( p_argument_buffer, command_line.c_str(), command_line.size() - 1 ); // Strip the trailing space

    printf( "Executing:-\n\tProcess: %s\n\tArguments: %s\n", argv[1], p_argument_buffer );

    // Set the starting parameters
    STARTUPINFO startup_info = { 0 };
    startup_info.cb = sizeof( startup_info );
    startup_info.dwFlags = STARTF_USESHOWWINDOW;
    startup_info.wShowWindow = SW_MINIMIZE;

    PROCESS_INFORMATION process_info = { 0 };

    // Start the child process. 
    BOOL create_status = CreateProcess( NULL,
                                        p_argument_buffer,
                                        NULL,
                                        NULL,
                                        FALSE,
                                        0,
                                        NULL,
                                        NULL,
                                        &startup_info,
                                        &process_info );

    // Free up our command line
    delete[] p_argument_buffer;

    // Either wait, or throw an error
    if ( create_status == 0 )
    {
        printf( "ERROR (0x%08x): Could not create process %s\n", GetLastError(), argv[1] );
    }
    else
    {
        printf( "Waiting... " );

        // Wait for the process to finish
        WaitForSingleObject( process_info.hProcess, INFINITE );

        // Close process and thread handles.
        CloseHandle( process_info.hProcess );
        CloseHandle( process_info.hThread );

        printf( "Finished\n" );
    }

    return ( create_status == 0 ? -1 : 0 );
}

Enjoy!

POKEMAN SAM
Jul 8, 2004

more falafel please posted:

Looks like at least some browsers (Safari at least) treat & p i ) ; as & p i ;, which should render as the pi symbol.

I see the PI symbol, and I'm on Firefox 2. Looks like & p i itself makes the PI symbol (it ignores the character following it, i.e. doesn't wait for a semi-colon.)


&pi

Vanadium
Jan 8, 2005

It is not browser specific, the forums do the substitution. You can tell by looking at the source. :ssh:

tef
May 30, 2004

-> some l-system crap ->

Vanadium posted:

It is not browser specific, the forums do the substitution. You can tell by looking at the source. :ssh:

Except I see &pi in Opera in the posts above, not π

POKEMAN SAM
Jul 8, 2004

Vanadium posted:

It is not browser specific, the forums do the substitution. You can tell by looking at the source. :ssh:

What? The source shows me the & p i, not the symbol.

Vanadium
Jan 8, 2005

Fun, I get a pi symbol if I use the View Selection Source button, but a &pi if I use the regular View Source one. Blaming a javascript substitution :argh:

Vanadium fucked around with this message at 21:08 on Jun 25, 2008

ValhallaSmith
Aug 16, 2005
Anyone know which TR1 standard library has better performance? Usually I'd just use Boost's TR1 imp, but VS2008 has it available now as well. Function objects is the main thing I'm after.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
The differences are probably negligible, and since they're both implementing the same standard, you can switch later on if you find that a particular implementation is unreasonably slow.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.

Vanadium posted:

It is not browser specific, the forums do the substitution. You can tell by looking at the source. :ssh:
If you view the source in Firefox, it shows you the source as modified by FF, not the original.

Allie
Jan 17, 2004

Mustach posted:

If you view the source in Firefox, it shows you the source as modified by FF, not the original.

Actually, this is only true if you view the source of a selection.

tyrelhill
Jul 30, 2006
I'm trying to const_cast a class * const to a class * and getting an access violation exception. I'm guessing there's some assembly optimizations with pointer consts that I dont know?

TSDK
Nov 24, 2003

I got a wooden uploading this one

tyrelhill posted:

I'm trying to const_cast a class * const to a class * and getting an access violation exception. I'm guessing there's some assembly optimizations with pointer consts that I dont know?
Modifying an object that was declared as const is undefined behaviour. You can only (safely) cast away const-ness to modify something if you know it was declared non-const.

tyrelhill
Jul 30, 2006
Ah, I guess I won't be doing that little hack then... Thanks!

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
I'm learning how to program in C++, using the Windows API, and as a project to focus on I'm trying to program a computer implementation of an obscure board game.

I'm currently learning how to use user-defined buttons, that is buttons with the BS_OWNERDRAW style. I managed to successfully get the application to create a button, paint it using a bitmap picture of the same size as the button, and handle the BN_CLICKED message to do something (change the value of a single variable, and redraw the parent window). Now I want to have two such buttons and have each one do something different, but I am having problems getting the handlers to do different things based on the button that sends the message. I think the problem is one of obtaining the correct HWND.

Here is the code I used to create the buttons; it is in the WM_CREATE case in the WindowProcedure function.

code:
    HWND page2btn =
    CreateWindow("BUTTON","Page2",WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_OWNERDRAW,
                 890,640,48,48,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
HWND page3btn =
    CreateWindow("BUTTON","Page3",WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_OWNERDRAW,
                 945,640,48,48,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
Here is the entire code for WM_DRAWITEM. (I think the problem I have with WM_COMMAND case BN_CLICKED is a similar one.) hbmOld is an HBITMAP, defined in the global scope and deleted when WM_CLOSE is handled. drawemptyp and drawemptyr are 48 x 48 HBITMAPS, also defined in the global scope (but initialised when WM_CREATE is handled) and deleted when WM_CLOSE is handled.

code:
case WM_DRAWITEM:
    LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT) lParam;
    if(lpDrawItem -> itemAction == ODA_DRAWENTIRE) {
        HDC hdcMem2 = CreateCompatibleDC ( lpDrawItem -> hDC );
        if (lpDrawItem -> hwndItem == page2btn) {                //Comment this out and it works
            GetObject(drawemptyp,sizeof(bm),&bm);
            hbmOld=(HBITMAP)SelectObject(hdcMem2,drawemptyp);
            BitBlt(lpDrawItem -> hDC,0,0,bm.bmWidth,bm.bmHeight,hdcMem2,0,0,SRCCOPY);
        } else if (lpDrawItem -> hwndItem == page3btn) {         //Comment this out and it works
            GetObject(drawemptyr,sizeof(bm),&bm);
            hbmOld=(HBITMAP)SelectObject(hdcMem2,drawemptyr);
            BitBlt(lpDrawItem -> hDC,0,0,bm.bmWidth,bm.bmHeight,hdcMem2,0,0,SRCCOPY);
        }                                                        //Comment this out and it works
        DeleteDC(hdcMem2);
    }
    break;
The problem I have is that with the above code, the buttons don't get painted. However, if I comment out the lines indicated, then it will paint both buttons using the "drawemptyr" image, the second one. This suggests that the "if" statements both evaluate to false, and in that case page2btn and page3btn must not be the right HWNDs. But that's what the HWNDs should be called, because that's what I specified when I created the buttons earlier on, shouldn't they?

EDIT: Never mind! I sorted it out by myself. Needed to declare the HWNDs page2btn and page3btn in the global scope and merely assign them to windows in the WM_CREATE code.

Hammerite fucked around with this message at 18:13 on Jun 27, 2008

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Hammerite posted:

I'm learning how to program in C++, using the Windows API

Good God, why?

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
I decided it would be quite cool to be able to say I'd actually learned a programming language.

When I was a kid we used to have a BBC Microcomputer with Basic on it, and I'd muck around writing little noddy programs on it that didn't do anything very interesting, but I never really learned to do anything advanced. I know how to use HTML and LaTeX (markup languages), but couldn't actually claim to know any programming languages.

As for why that language, I knew that a lot of stuff is programmed in C++. And for the "Windows API" part... bear in mind that that is my attempt to describe what I'm doing. I don't have a perfect command of all the technical terms involved here, and I may have inadvertently said I'm doing something I'm not. I'm creating a program to run in Windows, that displays graphics on the screen and that the user interacts with by clicking buttons. That's what I mean by what I said. I guess what I meant was "Windows GUI". I did a few little exercises that involved console programs first, but then graduated to making Win32 programs.

Adhemar
Jan 21, 2004

Kellner, da ist ein scheussliches Biest in meiner Suppe.

Hammerite posted:

I decided it would be quite cool to be able to say I'd actually learned a programming language.

When I was a kid we used to have a BBC Microcomputer with Basic on it, and I'd muck around writing little noddy programs on it that didn't do anything very interesting, but I never really learned to do anything advanced. I know how to use HTML and LaTeX (markup languages), but couldn't actually claim to know any programming languages.

As for why that language, I knew that a lot of stuff is programmed in C++. And for the "Windows API" part... bear in mind that that is my attempt to describe what I'm doing. I don't have a perfect command of all the technical terms involved here, and I may have inadvertently said I'm doing something I'm not. I'm creating a program to run in Windows, that displays graphics on the screen and that the user interacts with by clicking buttons. That's what I mean by what I said. I guess what I meant was "Windows GUI". I did a few little exercises that involved console programs first, but then graduated to making Win32 programs.

Learning C++ is fine in itself (though I definitely would not recommend it as your first language to learn), that's not what caused JoeNotCharles' reaction. It's your decision to program directly on top of the Windows API. I've been programming in C++ for years, but I wouldn't do that unless someone paid me a very large sum of money, or put a gun to my head.

If you're finding yourself using an ugly API to manually add buttons to your app in code, and tying even handlers to them; you know you're doing something wrong. This is 2008. Even Microsoft doesn't want you to do this anymore. If you know your app only needs to run on Windows, learn C# and program using .NET. It's much more fun, trust me. You'll have your GUI up in no time and you'll be able to focus on coding the stuff that actually matters to you.

If you're set on learning C++ right away, start with some console based apps, then move on to learning something like Qt if you want to do GUI apps. As an extra bonus your app will also run on other OSes.

Zombywuf
Mar 29, 2008

Adhemar posted:

If you're set on learning C++ right away, start with some console based apps, then move on to learning something like Qt if you want to do GUI apps. As an extra bonus your app will also run on other OSes.

And you won't be writing resize handlers manually.

vanjalolz
Oct 31, 2006

Ha Ha Ha HaHa Ha
That said, a peek into the Windows API is kind of cool. Nice to actually understand what people mean when they say 'message driven' and 'everything is a window'.

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe
The Win32 API pretty simple once you get it initially figured out, I like the way it's structured and everything for the most part is well documented on MSDN. Maybe I'm weird, but I much prefer using the API vs something like C#.

I love small, fast, native code that I feel like I have complete control over. The last thing a wrote was a little starfield effect in GDI to learn some of it. It compiled to 3.5kb, it needs nothing to run, it even avoids the CRT.

If you don't want to create the controls yourself, just use dialogs, or let this generate you some code. http://www.resedit.net/

Maybe in a situation where you need to pound out something fast, I could see the justification, but since I just code for my own amusement, I like this route.

Zombywuf
Mar 29, 2008

slovach posted:

The Win32 API pretty simple once you get it initially figured out, I like the way it's structured and everything for the most part is well documented on MSDN. Maybe I'm weird, but I much prefer using the API vs something like C#.

Yeah, you're weird. Hello world in Win32. It's almost as bad as X. For reference here's GTK and Qt.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

vanjalolz posted:

That said, a peek into the Windows API is kind of cool. Nice to actually understand what people mean when they say 'message driven' and 'everything is a window'.

I was thinking exactly this; I get that I might have chosen a non-standard route that's a lot of extra work, but doing everything "the hard way" has at least taught me how a lot of things work!

And like slovach said, I'm just doing this for my own amusement, and I find satisfaction in achieving a lot of things that more serious users of the language would probably regard as trivial and worth delegating to a piece of development software. (Though admittedly it can be frustrating when I can't make them work.)

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Zombywuf posted:

Yeah, you're weird. Hello world in Win32. It's almost as bad as X. For reference here's GTK and Qt.

Yeah and here's Hello World in MUMPS:
code:
W "Hello, world!",!
A "Hello world" program isn't a good indicator of the usability of a language/API. That said, Win32 isn't exactly easy to work with, but at least it's fairly internally consistent. It does drive me a little insane trying to mix the C++ STL with Win32, since Win32 uses capital letters all over the drat place. :argh:

Zombywuf
Mar 29, 2008

Avenging Dentist posted:

A "Hello world" program isn't a good indicator of the usability of a language/API. That said, Win32 isn't exactly easy to work with, but at least it's fairly internally consistent. It does drive me a little insane trying to mix the C++ STL with Win32, since Win32 uses capital letters all over the drat place. :argh:

When you've got to make use of multiple classes and a ton of preprocessor macros to get hello world, something is wrong.

floWenoL
Oct 23, 2002

What do you guys think of this?

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe

Zombywuf posted:

Yeah, you're weird. Hello world in Win32. It's almost as bad as X. For reference here's GTK and Qt.

You're making it sound more complicated than it is. But if you don't like creating everything yourself, just use a dialog. It'll handle the message loop, creating everything and all that work for you. Couldn't be easier! Creating it yourself is barely more work than this.

code:
BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case WM_INITDIALOG:
		DoShit();
		break;
	case WM_CLOSE:
		EndDialog(hwnd, 0);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return FALSE;
	}
	return ERROR_SUCCESS;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	hInstance = GetModuleHandle(NULL);
	DialogBox(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, DlgProc);
	return ERROR_SUCCESS;
}
edit:oops nobody saw that.

slovach fucked around with this message at 23:02 on Jun 29, 2008

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?

floWenoL posted:

What do you guys think of this?

The first thing is that it shouldn't be used as an all-purpose C++ coding guide. For instance, Google C++ code does not use exceptions, ever. This makes sense in the context of the performance requirements that Google's production code has, but there are plenty of instances where using exceptions is the better choice for purposes of legibility and maintainability.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Zombywuf posted:

When you've got to make use of multiple classes and a ton of preprocessor macros to get hello world, something is wrong.

Well, it would help if the guy who wrote that tutorial wasn't trying to shoehorn OO stuff into a C library. :colbert:

This is a better example, and even so, the guy is doing a lot more with the WNDCLASSEX structure than is strictly necessary for a Hello world app.

Paradoxish
Dec 19, 2003

Will you stop going crazy in there?

Zombywuf posted:

When you've got to make use of multiple classes and a ton of preprocessor macros to get hello world, something is wrong.

Except that "basic" example of Win32 includes a wrapper class. The Win32 API is a C library so it's obviously going to require some work if you absolutely must make it OO. I actually really like the Win32 API and find it pretty straightforward in the same way that I find C straightforward, but I still don't use it often since I recognize how much easier it is to be productive using .NET, QT, or just about anything else.

If I didn't care about being productive I'd write more Win32 API stuff, though. I need some sort of Win32 support group. :smith:

Smackbilly posted:

but there are plenty of instances where using exceptions is the better choice for purposes of legibility and maintainability.

Not that I'm agreeing that "don't use exceptions" is good general C++ advice, but there are still some points worth taking home in that section. In particular:

quote:

Exception safety requires both RAII and different coding practices. Lots of supporting machinery is needed to make writing correct exception-safe code easy.

Writing good, exception safe code in C++ is tricky because of the lack of a finally block. Without RAII you end up with either very messy exception handling code all over the place or the potential to leave resources hanging around that should have been cleaned up. It's pretty difficult to get around this for non-trivial programs if you aren't using shared_ptr or another reference counted smart pointer.

This also makes it twice as dangerous when someone inexperienced comes along and uses exceptions as an alternate return method or an error flag for non-exceptional conditions.

more falafel please
Feb 26, 2005

forums poster

floWenoL posted:

What do you guys think of this?

There's some stylistic issues I don't agree with that people have been arguing about for 30 years (wtf uses 2 spaces) but other than that I think it's pretty sane.

Some day I'll post the tale of mustDeref() and make you all converts.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

more falafel please posted:

There's some stylistic issues I don't agree with that people have been arguing about for 30 years (wtf uses 2 spaces) but other than that I think it's pretty sane.

I never understood people who advocate spaces in general. Tabs for indenting, spaces for vertical alignment. It's not hard to format code that's portable to different tab-widths.

Also the "no using in .cc files" rule is laffo. That's pretty much the only place you should have using declarations.

more falafel please
Feb 26, 2005

forums poster

Avenging Dentist posted:

Also the "no using in .cc files" rule is laffo. That's pretty much the only place you should have using declarations.

I understand it. They also say to eschew abbreviations in naming. using declarations are just abbreviations, really.

I'm not saying I particularly like it, but I don't really have an opinion.

floWenoL
Oct 23, 2002

Avenging Dentist posted:

Also the "no using in .cc files" rule is laffo. That's pretty much the only place you should have using declarations.

The wording is confusing, but if you expand the arrow, it explains that you are allowed to use using in .cc files.

And yes, for anyone who isn't aware, the arrows do something, namely provide more details.

Dransparency
Jul 19, 2006

floWenoL posted:

What do you guys think of this?

Personally I think this is disgusting:

code:
// When it requires multiple lines, indent 4 spaces, putting the colon on
// the first initializer line:
MyClass::MyClass(int var)
    : some_var_(var),             // 4 space indent
      some_other_var_(var + 1) {  // lined up
  ...
  DoSomething();
  ...
}
What's the logic behind the colon getting a newline but the opening brace not? I'm not trying to start a brace style war, but if you've elected to use K&R for braces, why not use something similar for colons?

The indentation also bothers me. I would much rather have lines move to the right the farther I read into the function, rather than the weird shifting going on here.


I also don't like the bit on function naming. It seems like it could introduce inconsistencies if there isn't a direct relationship between public characteristics and internal implementation variables.



Edit: I'd be interested in hearing what the rest of you think about the section on streams in particular. Not just for Google's case (where they need to maintain consistency with old code) but for general practice programming. The guide seems to dismiss the issue as "they both have pros and cons, so either one is just as good."

Dransparency fucked around with this message at 04:35 on Jun 30, 2008

That Turkey Story
Mar 30, 2003

floWenoL posted:

What do you guys think of this?

I just skimmed and it's not bad, but some stuff I do disagree with. I will probably make it sound worse than it is because I get really upset when people give foolish rationales, but really nothing in here is horrible.

quote:

All inheritance should be public. If you want to do private inheritance, you should be including an instance of the base class as a member instead.

In modern C++ there are lots of reasons to prefer private inheritance rather than datamembers in certain situations, some of which are techniques that simply only work with inheritance as opposed to composition. For one, private inheritance is useful for minimizing redundancy by inheriting from a base and pulling in desired names with a using declaration rather than having to tediously create I.E. forwarding functions (which can be error prone and less efficient if not done carefully, not to mention potentially less clear). Another example is helper bases that pull in functions that can be looked up via ADL (I.E. Boost.Operators). As well, using inheritance let's you take advantage of the empty base optimization, which as a side note, is exactly how Boost compressed pair works which is on this list's approved Boost libraries -- the only approved component of Boost on the list actually (so basically the guide doesn't want you to do private inheritance, but it's okay to use it indirectly, which stinks of Java's operator + logic to me).

quote:

Only very rarely is multiple implementation inheritance actually useful. We allow multiple inheritance only when at most one of the base classes has an implementation; all other base classes must be pure interface classes tagged with the Interface suffix.
This kind of goes back to what I was just talking about : particularly with private inheritance, multiple inheritance is common and often desired. It's true that multiple public inheritance is often a bad choice (though even then not always), but issues aren't really there with the modern uses of inheritance in C++. Again, Boost.Operators is a great example of this.

quote:

Use 0 for integers, 0.0 for reals, NULL for pointers, and '\0' for chars.
Back in C, NULL was much more of an option to consider since it could be defined as ((void*)0) since implicit conversion from void* to other pointer types is implicit in C (whereas void* to integral is not implicit in C or C++). In C++, however, NULL is pretty much limited to being defined strictly as 0 unless your compiler defines it in some way outside the realm of a normal #define and it provides little benefit over just using a raw 0 other than possibly to signal the context of a pointer in text or the chance that your compiler makes a special case for NULL (which most do not). As well, the only way you can [portably] use NULL is if you include certain standard library files which can be silly since 0 works just fine. If you really want to have a different name from 0 to use for null pointers, it's generally best to use a custom null-pointer object, which can let you make a more proper solution than a simple macro. NULL is more of a legacy from C that carried over as some people switched from C to C++.

quote:

Do not overload operators except in rare, special circumstances.

...

Cons: While operator overloading can make code more intuitive, it has several drawbacks:

* It can fool our intuition into thinking that expensive operations are cheap, built-in operations.
* It is much harder to find the call sites for overloaded operators. Searching for Equals() is much easier than searching for relevant invocations of ==.
* Some operators work on pointers too, making it easy to introduce bugs. Foo + 4 may do one thing, while &Foo + 4 does something totally different. The compiler does not complain for either of these, making this very hard to debug.

...

In general, do not overload operators. The assignment operator (operator=), in particular, is insidious and should be avoided. You can define functions like Equals() and CopyFrom() if you need them.

...

Some of the STL algorithms do require you to overload operator==, and you may do so in these cases, provided you document why.

This I disagree with entirely. First, I don't understand this talk about people expecting operations to be "cheap" (or even what the vague term of "cheap" means in the general sense). You expect the operation to do what it's supposed to do, and if there is a required complexity for a given domain at concept then it should be made known. Multiplying two matrices might be expensive, but it's still a multiplication operation. Concatenating strings with + is intuitive. Anyone who somehow thinks that using a named function called "multiply" does anything other that make you type more and make it harder for your object to be used in generic code is simply not used to a language with operator overloading and that's it. There is nothing special about operators that makes them any different from other operations other than syntax and this whole nonsensical idea of them having to be "cheap" is just silly.

As well, the comment "Foo + 4 may do one thing, while &Foo + 4 does something totally different" really just blows my mind in that I can't believe somebody genuinely thinks this is a good point. Are they trying to tell me that at some point in code somebody honestly accidentally wrote &Foo + 4 instead of Foo + 4, and after doing that, it somehow bit them in the rear end rather than being caught by the compiler? Are they also missing out on the point that what they are saying would be true of integers and the built-in operator +? Maybe they are suggesting that people should use a named "Add" operation for built-in arithmetic types as well, since that goes along with their argument?

Anyway, aside from that being an odd mistake to make to begin with and the fact that their "rationale" would apply to built-in operators, the expression given would likely never occur alone like that in a statement as it would be a part of a larger expression, since unless the + expression they showed has side-effects, you'd be losing any calculation being made anyway (and if the statement has no side effects, that typo would generally make no difference since there is no observable change either way, though you technically might get undefined behavior with the &Foo + 4 depending on context, but even I'll say that's a moot point and I'm a pretty pedantic language lawyer).

Anyway, getting back to what this means -- this "&Foo + 4" expression will be a sub-expression of something else, for instance, you'd store the result of the plus operation in another object or pass the result to a function. C++ is a statically-typed language, so unless the rest of the expression can take a pointer as an argument or an object of whatever the result type of the + is here, you'd get a compiler error so you'd know your mistake right away! I find it extremely hard to believe that anything like what they described has or ever will occur in any competent [or incompetent] person's code.

The fact is, using + makes perfect sense here for built-in arithmetic types, pointer types, and user-defined types. Barring contrived examples that don't even make sense, you have to really push to come up with sound reasons against them as opposed to being driven by blind, religious issues with operator overloading.

Finally, they claim that overloading the assignment operator is bad as well along with the equality operator. I find it extremely hard to believe that using "Equals" instead of "==" is more clear or less error prone. Again, all I see it accomplishing is making it harder to have your objects work in generic code and making it seem like operators are some special devices that are only for use with built-ins. Their excuse that it makes it easier to search for in code is also very weak considering all you're doing is weeding out built-in operations, whereas if all of your user-defined types use the same name (I.E. Equals) you have the same exact "problem" (which I can't even really see as being a problem to begin with).

All of their issues with operators are extremely contrived and sound like worries that people might have if they worked their whole life in another language and got an idea stuck in their head of what they personally think an operator should be as opposed to what operators really are, at least with respect to C++.

quote:

All parameters passed by reference must be labeled const.

This is C++. You can pass objects as references, that's how the language works. Using non-const references for parameters which modify an object as opposed to a pointer is the preferred C++ way of having functions which modify arguments as it removes the issue of making it unclear about the handling of null pointers and overall it simplifies syntax. If it is unclear that an argument to a function should take a non-const reference then that is generally a poorly named function and/or the person trying to use it doesn't understand it's purpose, which either way is a programmer error. The only time I see people have issues with this are when they come from a C background where references just didn't exist so they just got used to always passing out parameters by pointer. There is a better solution in C++ so use it and stop clinging to an out-dated C-style approach.

quote:

If you want to overload a function, consider qualifying the name with some information about the arguments, e.g., AppendString(), AppendInt() rather than just Append().

This is just silly. Again, they all correspond to the same logical operation and having to repeat the type of your expression just to call the function is redundant, not to mention annoying. You also just once again make it harder to use the function in generic code.

quote:

We do not allow default function parameters.
link

...

Cons: People often figure out how to use an API by looking at existing code that uses it. Default parameters are more difficult to maintain because copy-and-paste from previous code may not reveal all the parameters. Copy-and-pasting of code segments can cause major problems when the default arguments are not appropriate for the new code.

Decision: We require all arguments to be explicitly specified, to force programmers to consider the API and the values they are passing for each argument rather than silently accepting defaults they may not be aware of.
First, if you are trying to figure out an API by copying and pasting code then you need to stop. If you don't understand the semantics of a function then why on earth are you calling it? At the very least, read the comment for the function. If you are naively copying a function call, alarms should be going off in your head questioning the semantics whether there are defaults or not.

quote:

You should not use the unsigned integer types such as uint32_t, unless the quantity you are representing is really a bit pattern rather than a number. In particular, do not use unsigned types to say a number will never be negative. Instead, use assertions for this.
Holy moly. Goodnight.

Edit: I don't know why you're getting all upset about naming and indentation, etc. You can't really fault anyone for something that's nearly entirely a subjective choice.

That Turkey Story fucked around with this message at 08:30 on Jun 30, 2008

Adbot
ADBOT LOVES YOU

more falafel please
Feb 26, 2005

forums poster

That Turkey Story posted:



Well put.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply