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
Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

What looping constructs have you tried? It's better that you try and think it through instead of just coming to this thread first.

Adbot
ADBOT LOVES YOU

Fatty_McLumpkin
Sep 30, 2002

Oh I loooove going to the mooon ahaha ahhhahaaa

Dijkstracula posted:

What looping constructs have you tried? It's better that you try and think it through instead of just coming to this thread first.

thank you for this response...

I just tried it with a while loop (in place of the if, and replace the else if with just an if)) and got the result I was looking for.

....now to try to figure out how to code in the error reporting for months that have 31 versus 30 days. :psyduck:

Fatty_McLumpkin fucked around with this message at 04:43 on Dec 16, 2009

raminasi
Jan 25, 2005

a last drink with no ice
I have a third-party library that, when it does its thing, writes to stdout. I want it to not do this. It seems like I might be able to use freopen somehow, but I don't know how to redirect stdout to nowhere before I execute the library function (I'm on windows, so no /dev/null) and back to what it was afterward, or even if this is the way to go.

edit: there actually was an option to turn this off squirreled away somewhere, but I'm still curious about whether this is possible

raminasi fucked around with this message at 23:09 on Dec 18, 2009

pseudorandom name
May 6, 2007

GrumpyDoctor posted:

I have a third-party library that, when it does its thing, writes to stdout. I want it to not do this. It seems like I might be able to use freopen somehow, but I don't know how to redirect stdout to nowhere before I execute the library function (I'm on windows, so no /dev/null) and back to what it was afterward, or even if this is the way to go.

edit: there actually was an option to turn this off squirreled away somewhere, but I'm still curious about whether this is possible

freopen("\\\\.\\Device\\Null", "w", stdout) might work.

tripwire
Nov 19, 2004

        ghost flow

GrumpyDoctor posted:

I have a third-party library that, when it does its thing, writes to stdout. I want it to not do this. It seems like I might be able to use freopen somehow, but I don't know how to redirect stdout to nowhere before I execute the library function (I'm on windows, so no /dev/null) and back to what it was afterward, or even if this is the way to go.

edit: there actually was an option to turn this off squirreled away somewhere, but I'm still curious about whether this is possible

You can redirect to nul! its the same thing!

raminasi
Jan 25, 2005

a last drink with no ice
If I copy an object of a class without an explicitly-defined copy constructor but with a superclass with one, what gets called?

That Turkey Story
Mar 30, 2003

GrumpyDoctor posted:

If I copy an object of a class without an explicitly-defined copy constructor but with a superclass with one, what gets called?

The default copy constructor calls the base class copy constructors and member copy constructors.

RussianManiac
Dec 27, 2005

by Ozmaugh
Can somebody drop some words of wisdom upon const references and returning them in a function?

Specifically what I want to do is return a reference to my internal object but as const to make sure it is not modified once it is returned.

Should I just return a const pointer instead? I'm sorry my C++ is rusty and I would like to hear from professionals on this matter, and what sort of pitfals there could be to this.

floWenoL
Oct 23, 2002

RussianManiac posted:

Can somebody drop some words of wisdom upon const references and returning them in a function?

Specifically what I want to do is return a reference to my internal object but as const to make sure it is not modified once it is returned.

Should I just return a const pointer instead? I'm sorry my C++ is rusty and I would like to hear from professionals on this matter, and what sort of pitfals there could be to this.

I can't think of a reason to return a pointer-to-const over a const reference for an accessor.

RussianManiac
Dec 27, 2005

by Ozmaugh

floWenoL posted:

I can't think of a reason to return a pointer-to-const over a const reference for an accessor.

explain please.

Aramis
Sep 22, 2009



floWenoL posted:

I can't think of a reason to return a pointer-to-const over a const reference for an accessor.

That's not true at all. If your member is dynamically allocated you better use a pointer instead, on account of the whole "dereferencing a NULL is kinda bad". You could make an argument that for members that are allocated at construction time dereferencing the pointer in a reference would be safe(ish). But that's asking for trouble in the long run.

However, if the member is not a pointer, a reference is always better.

Simple rule of thumb: A reference -> equivalent pointer cast is always fine. If you ever have to do pointer -> reference then something has generally gone wrong. Because of that, always use references where possible, since you can always bail to a pointer if something requires it anyways.

Edit: I am talking about high-level organizational structures here. Operators and small operations are a different matter.

Aramis fucked around with this message at 08:28 on Dec 21, 2009

Paniolo
Oct 9, 2007

Heads will roll.

Aramis posted:

That's not true at all. If your member is dynamically allocated you better use a pointer instead, on account of the whole "dereferencing a NULL is kinda bad". You could make an argument that for members that are allocated at construction time dereferencing the pointer in a reference would be safe(ish). But that's asking for trouble in the long run.

code:
assert(m_ptr != nullptr);
return *m_ptr;
Or throw an exception. The rule of thumb is returning a pointer indicates that the function may optionally return NULL and the caller must check for this. When returning a reference, the function takes responsibility to ensure that a valid object is returned, and the caller does not have to perform any checking.

You can also use boost::optional instead of a pointer to achieve the same behavior.

Paniolo fucked around with this message at 09:29 on Dec 21, 2009

That Turkey Story
Mar 30, 2003

RussianManiac posted:

explain please.

If you are guaranteed to have an object and don't want to allow the returning of null, there is no reason to return a pointer and I'd go so far as to say it would be worse to do so. By giving the user of the function a pointer you are not implicitly communicating the fact that you will always retrieve a valid object. The reference gives the user more information.

Aramis posted:

That's not true at all. If your member is dynamically allocated you better use a pointer instead, on account of the whole "dereferencing a NULL is kinda bad". You could make an argument that for members that are allocated at construction time dereferencing the pointer in a reference would be safe(ish). But that's asking for trouble in the long run.

What are you talking about? Whether or not it was dynamically allocated and/or referenced internally as a pointer is an implementation detail. If the function is supposed to always yield a valid object then a reference or a copy is going to be better. The only time it ever makes sense to return a pointer is if, by design, the user of the function should expect a null pointer. The poster of the question said nothing of the sort.

Aramis posted:

Simple rule of thumb: A reference -> equivalent pointer cast is always fine. If you ever have to do pointer -> reference then something has generally gone wrong.
I'm sorry, but that's total poo poo. There is nothing wrong with dereferencing a pointer and forming a reference unless you have a null pointer, which you either know by design or by an explicit check. Something has not "generally gone wrong" when you are correctly working with dynamically allocated memory or simply working through indirection and you need to form a reference from a pointer.

Aramis
Sep 22, 2009



Paniolo posted:

code:
assert(m_ptr != nullptr);
return *m_ptr;
Or throw an exception.

The fact that it's feasible changes nothing to the issue at hand. C++ is riddled with ways to do things that work but are totally inadvisable until you are painted in a corner. const_cast is a great (possibly best) example of this. In your example, if the pointer is null, you still de-reference it (in a release build). It's way, way safer to address this at the call point of the function.

code:
MyClass * ptr = obj.getPtr() ;
if( ptr )
{
  //this is fine unless we have a dangling or uninitialized pointer
  call_function_that_takes_a_reference( *ptr ) ;
}
I cannot stress this point enough, and I get pissed at junior programmers on a regular basis for it: possible/works != license to use.

edit:

That Turkey Story posted:

I'm sorry, but that's total poo poo. There is nothing wrong with dereferencing a pointer and forming a reference unless you have a null pointer, which you either know by design or by an explicit check. Something has not "generally gone wrong" when you are correctly working with dynamically allocated memory or simply working through indirection and you need to form a reference from a pointer.

Remember the context, we are talking about an accessor here. Which means that there is no possibility of a fallback, unless you throw an exception you'll need to dereference something.

Aramis fucked around with this message at 09:35 on Dec 21, 2009

That Turkey Story
Mar 30, 2003

Aramis posted:

The fact that it's feasible changes nothing to the issue at hand. C++ is riddled with ways to do things that work but are totally inadvisable until you are painted in a corner. const_cast is a great (possibly best) example of this. In your example, if the pointer is null, you still de-reference it (in a release build). It's way, way safer to address this at the call point of the function.
It's an assert because the only way it would null is if the programmer made a mistake. It should either never be null in release or it should be documented that it is undefined behavior if you call the function in situations where the pointer may be null. That's why it's an assert to begin with and not the throwing of an exception or some kind of branching.

As an example, if you write a smart pointer and are making operator* you generally make it assert that you have a pointer to a valid object since dereferencing a smart pointer that is null, much like dereferencing a regular pointer that is null, is undefined behavior. The same applies to any other function.

Aramis posted:

I cannot stress this point enough, and I get pissed at junior programmers on a regular basis for it: possible/works != license to use.
Not to be an rear end, but it sounds like they know better than you.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Aramis posted:

It's way, way safer to address this at the call point of the function.

code:
MyClass * ptr = obj.getPtr() ;
if( ptr )
{
  //this is fine unless we have a dangling or uninitialized pointer
  call_function_that_takes_a_reference( *ptr ) ;
}
I cannot stress this point enough, and I get pissed at junior programmers on a regular basis for it: possible/works != license to use.

edit:

Remember the context, we are talking about an accessor here. Which means that there is no possibility of a fallback, unless you throw an exception you'll need to dereference something.

So, in the fallback case of that if you wrote after the callpoint, what exactly do you propose gets done? Call assert_not_reached? Throw an exception? Do nothing, and violate whatever contract you were hoping to provide to code downstream? Why is it any better that these things are done at the callpoint, where they'll presumably have to be retyped every time the accessor is used, with all the potential for bugs that entails, rather than doing them once inside the function itself?

Seriously, a reference return is the way to write functions that guarantee they always return valid memory. It is perfectly valid to write such functions even in systems with dynamic allocation because a dynamic allocation failure is possibly the single most obvious example of an exceptional condition, which is what exceptions are for. You shouldn't clutter up your contracts with extremely unlikely conditions that require 99% of your callers to duplicate the same boilerplate code at every callsite; just write the contract to the common case, and signal failure with an exception, which the 1% of callers who are capable of handling such a situation can easily catch.

RussianManiac
Dec 27, 2005

by Ozmaugh
I love you guys so much. Thanks.

That Turkey Story
Mar 30, 2003

Aramis posted:

Remember the context, we are talking about an accessor here. Which means that there is no possibility of a fallback, unless you throw an exception you'll need to dereference something.

If that's the case then your object is in an invalid state, meaning that either the class was designed poorly or the operation that put the object into an invalid state should have alerted users at a previous point (either by exception, or some kind of error flag if you are avoiding exceptions, etc.). By relaxing the requirements of the function to return a pointer instead of a reference for the paranoia that the object might be in an invalid state rather than correctly handling the problem at its source you only succeed at complicating both the function and all of the users of the class, not to mention that you are needlessly exposing implementation details and missing a much more fundamental problem with the design of your class.

Paniolo
Oct 9, 2007

Heads will roll.

Aramis posted:

The fact that it's feasible changes nothing to the issue at hand. C++ is riddled with ways to do things that work but are totally inadvisable until you are painted in a corner. const_cast is a great (possibly best) example of this. In your example, if the pointer is null, you still de-reference it (in a release build). It's way, way safer to address this at the call point of the function.

Way to completely ignore the part where I said "or throw an exception", which is strange because you even quoted it.

Aramis posted:

Remember the context, we are talking about an accessor here. Which means that there is no possibility of a fallback, unless you throw an exception you'll need to dereference something.

This is exactly what exceptions are for. You're basically saying, "Sure we could use the built-in language construct design to handle this situation, or we could just pass the responsibility onto the callers and force them to add boilerplate error-checking code at every call site."

I would hate to work with any API you designed.

The1ManMoshPit
Apr 17, 2005

I usually write my member accessors following this pattern

code:
class A
{
public:
    error_state* getFoo(const int** outFoo) const;
private:
    int* foo;
};

error_state* A::getFoo(const int** outFoo) const throw(GlobalStateArrayNotAllocatedException, GlobalStateArrayReturnedNullException)
{
    if (GlobalStateArray::instance() == NULL)
        throw GlobalStateArrayIsNullException();

    error_state* return_state = NULL;

    if (this == NULL)
    {
        return_state = GlobalStateArray::instance()->getError(kThisIsNull);
    }
    else if (outFoo == NULL)
    {
        return_state = GlobalStateArray::instance()->getError(kArgumentIsNull);
    }
    else
    {
        *outFoo = foo;
        return_state = GlobalStateArray::instance()->getError(kSuccess);
    }

    if (return_state == NULL)
    {
        throw GlobalStateArrayReturnedNullException();
    }

    return return_state;
}

The benefit of this is that I cover all cases. Now the calling code knows exactly what went wrong internally!

code:
A a;

int* aFoo = NULL;

try
{
    error_state* es = a.getFoo(&aFoo);

    if (GlobalStateArray::instance() == NULL)
        throw GlobalStateArrayIsNullException();

    switch (GlobalStateArray::instance()->decodeError(es))
    {
        case kThisIsNull:
        case kArgumentIsNull:
            throw CompilerErrorTurnedLocalStackVariableNullException();
            break;
        case kSuccess:
            if (aFoo == NULL)
                throw FooWasNULLException();
            break;
        default:
            throw UnknownGlobalErrorStateReturnedException();
    }
}
catch (const GlobalStateException& e)
{
    logError("Global state exception logged at %s:%d", __FILE__, __LINE__);
    throw LoggedExceptionWrapper<GlobalStateException>(e);
}

// now we can do something with aFoo!
Now I'm guarded against every possible error that a programmer could have made, totally safe to call this, as long as you just remember to follow the simple calling procedure (unlike some asstard junior programmers I work with ;)).

Vinterstum
Jul 30, 2003

The1ManMoshPit posted:

code paranoia

You, sir, are a genius.

And kudos for first time I've ever seen a 'this == NULL' comparison done (which is actually kind of surprising).

Painless
Jan 9, 2005

Turn ons: frogs, small mammals, piles of compost
Turn offs: large birds, pitchforks
See you at the beach!
That's almost perfect, but I think you should change all instances of "if ( var == NULL )" to "if ( NULL == var )". You're not a real coder until you're afraid of the drop shadow effects of your own windows.

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


Sorry for asking this, but inheritance never fails to confuse the hell out of me. I've got a base Object class, from which I derive three other classes. I store the instances of these classes in a linked list, where each node contains anObject* pointer, so that it can take any of the three derived classes.

But when I call a function, say Update(), on the pointers it calls the function Update() as defined in Object and not in any of the derived classes. I could swear that this shouldn't happen - I could swear that I've tried something similar elsewhere in the code (when storing States) that worked, but I can't see a difference between the two.

I never get the nuances of inheritance/polymorphism/whatchamacallit. I've got code, but all the relevant bits are scattered here and there so I figured this would be a clearer explanation.

The1ManMoshPit
Apr 17, 2005

Is Update() declared virtual in the base Object class?

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.
Is Update() declared as virtual in Object?

Subway Ninja
Aug 24, 2005

I am slowly teaching myself the basics of C++, but for some reason I just cannot grasp the concept of certain pointer uses. I know what a pointer is and how to assign and access one, but directing input into an array of pointers is throwing me off.

code:
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
using namespace std;

int _tmain(int argc, int argv[])
{
	/* Initialize Variables */
	char *ptr_Names[10] =	//Initialize pointer array.
	{			//
		"","","","","",	//
		"","","","",""	//
	};			//
	int int_NumNames = 0;	//Initialize name counter. Input by user to determine number of loops.
	int i = 0;		//Initialize i. Used in 'for' loops.

	/* Function Prototypes */
	int fun_AnalyzeInput(int int_NumNames);

	while (!int_NumNames)	//Loop through function call until 'int_NumNames' is a valid, non-zero number.
	{								//
		cout << "How many names would you like to enter? ";	//Ask for input regarding number of entries to be made.
		cin >> int_NumNames;				        //Receive input.
		int_NumNames = fun_AnalyzeInput(int_NumNames);	        //Test input.
	}								//

	for (i=0; i<int_NumNames; i++)						        //Repeat loop for each name to be entered.
	{									        //
		cout << "Enter name (" << i+1 << " of " << int_NumNames << "):";	//Prompt user for name.
		cin >> *ptr_Names[i];							//Store name in array. <---THIS IS WHAT I CANNOT GET TO WORK.
	}

	cout << "You entered the following names: ";	//Display the names that were entered.
	for (i=0; i<int_NumNames; i++)			//Repeat loop for each name that was entered.
	{						//
		cout << ptr_Names[i] << endl;		//Display name.
	}						//

	return 0;	//Program Exit.
}

int fun_AnalyzeInput(int int_NumNames)
{
	if (!cin.good())	//Verify that a number was entered, as opposed to a letter or other invalid character.
	{			//
		cin.sync();	//If not, clear the cin buffer as well as the error flags.
		cin.clear();	//

		cout << "You must enter a number!" << endl;	//Inform the user that they need to enter a valid number.
		int_NumNames = 0;	                        //Set int_NumNames to 0 so that the function is called again.
	}
	else if (int_NumNames < 1 || int_NumNames >10)	//Verify that the number is between 1 and 10.
	{
		cout << "You must enter a number from one to ten!" << endl;	//Inform the user that they need to enter a valid number.
		int_NumNames = 0;						//Set int_NumNames to 0 so that the function is called again.
	}

	return int_NumNames;	//Return the value of 'int_NumNames' for program flow. A value of zero will call this function again.
}
Any advice as to how to finish this last conundrum, or general criticism of the code in general is welcome. I simply cannot figure out how to direct input into the pointer array.

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


The1ManMoshPit posted:

Is Update() declared virtual in the base Object class?

Mustach posted:

Is Update() declared as virtual in Object?

Yep.

code:
virtual void Update(float dt){};

ctz
Feb 6, 2003

Subway Ninja posted:


your program boils down to std::cin >> "";. This has two problems:

a) istream::operator>>(char *) reads some number of characters and writes them to the supplied address. The number of characters can be given an upper bound, but you didn't so this would be a buffer overrun. In any case, its a lovely misfeature akin to gets(3) -- don't use it.

b) "" is a string literal, a pointer to a single NUL. Writing to the address if a string literal is undefined behaviour, on modern implementations your program will segfault at this point.

in other words, use std::string already.

Subway Ninja
Aug 24, 2005

Thanks for the quick reply. I'm working through an online tutorial at MSDN so I hadn't gotten to std::string yet.

The1ManMoshPit
Apr 17, 2005

Staggy posted:

Yep.

code:
virtual void Update(float dt){};

Without more code it's going to be pretty hard to know exactly what your problem is. Are you sure the objects you're inserting into your list are actually instances of the derived classes and not the base class?

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


Well the linked list is made up of these lovely structures, so I would imagine this is what you're talking about.

code:
struct ObjNode
{
	ObjNode* BackPntr;
	ObjNode* NextPntr;
	Object*   Obj;
};
With this to add new nodes to the linked list:
code:
void ObjectManager::AddObj(Object o)
{
	while(GetNode()->NextPntr != NULL)
		NextObj();

	GetNode()->NextPntr = new ObjNode;
	GetNode()->NextPntr->BackPntr = GetNode();
	NextObj();

	GetNode()->NextPntr = NULL;

	GetNode()->Obj =  &o;
};
So I'm storing them all as the base class. Which could be a problem. But elsewhere I do this:
code:
std::vector <Scene*> SceneVec;
Storing derived classes like MenuScene. And this works.

I think this is the crux of the problem. But I was under the impression that you could store derived classes in this way and still have them remain the derived class. Or store them at all, as I'm currently having trouble with.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
http://en.wikipedia.org/wiki/Object_slicing

Make ObjectManager::AddObj take a pointer to an Object instead and it'll work

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


Plorkyeran posted:

http://en.wikipedia.org/wiki/Object_slicing

Make ObjectManager::AddObj take a pointer to an Object instead and it'll work

Thank you! This was exactly it! I've got the whole thing fixed now, and I'm aware of the issue in the future. Thanks again.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Staggy posted:

Thank you! This was exactly it! I've got the whole thing fixed now, and I'm aware of the issue in the future. Thanks again.

If you never want to create an Object directly, only via its subclasses, then you can get the compiler to catch this kind of mistake for you. Just make at least one method on Object "pure virtual", like so:

code:
virtual void Update(float dt) = 0;
Now the compiler will complain if you accidentally slice an object, as well as if you forget to implement Update in one of your subclasses.

Chuu
Sep 11, 2004

Grimey Drawer
I was being a little careless and something like this slipped into my code and compiled without warnings (and caused a nasty bug since the human-intuitive way to parse this is wrong):

code:
switch(value)
{
   case 1 : doStuff();
            break;
   if(someTest)
      {
         case 2: doMoreStuff();
		 break;
	 default:doEvenMoreStuff();
		 break;
      }
}
Is this really legal C++? Taking a quick look at the grammar on MSDN a "case" within an expression doesn't seem like it should be legal.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
That's perfectly legal and there's even semi-valid reasons to want to do it, such as Duff's device. Switch requires that the first case statement (or default) comes before any expressions in switch's body, but nothing says that subsequent case statements cannot be inside other statements.

RussianManiac
Dec 27, 2005

by Ozmaugh
If I have the Diamond Inheritance going on in my C++ project, then if all functions in the super class are virtual then i don't have any problems right? What if that super class also has a protected member variable?

Vanadium
Jan 8, 2005

itym virtual super class

RussianManiac
Dec 27, 2005

by Ozmaugh

Vanadium posted:

itym virtual super class

It is a super class that has virtual methods in it, yes, but also has a member variable.

Adbot
ADBOT LOVES YOU

OddObserver
Apr 3, 2009

RussianManiac posted:

It is a super class that has virtual methods in it, yes, but also has a member variable.

A virtual superclass isn't the same thing as a superclass with virtual member functions.

Edit, to be at least somewhat helpful: When doing inheritance, besides just saying
Foo: public Bar, you can also say Foo: public virtual Bar. You need the 'virtual'
to put things to be a diamond, and not to have 2 copies instead. I'll leave the details to you
or more helpful posters.

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