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
newsomnuke
Feb 25, 2007

digibawb posted:

You can't forward declare a type you are using as a base.
Oh of course, duh. Ignore me.

Adbot
ADBOT LOVES YOU

clearly not a horse
May 8, 2009

undue butt brutality is not a criminal offense
About vectors - say I want an object called "container" to function like a chest or a drawer. It has a limited capacity and can contain any object of some "heritage".

Let's assume I have several objects; banana, TV and a refrigerator - each of these are a subclass of the class SomeItem. They have some vital properties like size.
If I then add one object of the class banana into the vector, will it be treated as an object of the class SomeItem?

code:
vector<SomeItem*> items;

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

clearly not a horse posted:

About vectors - say I want an object called "container" to function like a chest or a drawer. It has a limited capacity and can contain any object of some "heritage".

Let's assume I have several objects; banana, TV and a refrigerator - each of these are a subclass of the class SomeItem. They have some vital properties like size.
If I then add one object of the class banana into the vector, will it be treated as an object of the class SomeItem?

code:
vector<SomeItem*> items;

Passing an object around by pointer or reference doesn't change its dynamic type, so turning a Banana* into a SomeItem* doesn't stop it from pointing to a Banana. That said, if you access the object through a SomeItem*, you will access it *as if* it were a SomeItem; the methods you invoke will be the methods declared on SomeItem, etc. That said, you can declare a method 'virtual' on SomeItem, and then when code calls it it will actually call whatever the "most overriding" method is according to the dynamic type.

Lexical Unit
Sep 16, 2003

rjmccall posted:

That said, if you access the object through a SomeItem*, you will access it *as if* it were a SomeItem
Mmm?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I stand by my explanation: behavior is determined by the static type, but the static type can define those behaviors in terms of the dynamic type.

This is a pretty important point to get across to someone used to a fully-dynamic type system.

Lexical Unit
Sep 16, 2003

I misunderstood your first post. That clears it up.

Le0
Mar 18, 2009

Rotten investigator!

ultra-inquisitor posted:

It's almost certainly a cyclic dependency, you need to forward declare one of the classes.

(file1.h)
code:
#pragma once
#include "file2.h"

struct foo : public bar {};
(file2.h)
code:
#pragma once

struct bar {};

struct foo; // forward declaration for baz

struct baz : public foo {};
Then #include file1.h in file2.cpp

Yes that's my problem, cyclic dependency, basically the compiler says that my type declared in file1.hpp is not known by file2.hpp.

I tried to do what you explained but yes it is not possible.
How should I fix this issue correctly ?

Foiltha
Jun 12, 2008
This is more of a Visual Studio question, but I figured this is the best thread to ask this. I'm relatively inexperienced with VS and after switching to Windows 7 decided to install VS 2010 Express. I added these existing items to a new project but for some reason the compiler isn't finding them. I've tried adding them from Project -> Add existing items as well as dragging them from Explorer. Both times the files show up just fine in the solution explorer but for some reason it's unable to find them. Am I doing something wrong here?

UraniumAnchor
May 21, 2006

Not a walrus.
Check your include paths.

Foiltha
Jun 12, 2008

UraniumAnchor posted:

Check your include paths.

I'm such an idiot. Thanks, works fine now.

clearly not a horse
May 8, 2009

undue butt brutality is not a criminal offense
http://pastebin.mozilla.org/731091

I want to ask yet another question which I can't seem to find a sensible answer to.
You may look at the above code where I try to make a "node" object that can hold other nodes in a vector of "children". Think about it as an attempt to model a hierarchical structure.
Or you may want to look at the smaller stripped down code beneath. Whenever A adds B as a child with the function addChild(), B should be removed from the "children" vector of its parent. This was pretty easy to do in Python where I easily could get the index of an object in a list based on it's value. Do I need to make elaborate function for this or is there some easy way to do this?

code:
class node {
	vector<node*> children;
	node* parent;
	
public:
	void addChild (node* target) {
		children.push_back(target);
		target->parent = this;
		target->parent->removeChild(target);
	}
	
	void removeChild(node* target) {
		children.erase(??????);	
	}
};

Lexical Unit
Sep 16, 2003

It might make more sense to have a set<node*> instead of a vector. Otherwise you would have to linearly search for the target to erase it. Not to mention erasing something from a vector also has linear computational complexity.

clearly not a horse
May 8, 2009

undue butt brutality is not a criminal offense

Lexical Unit posted:

It might make more sense to have a set<node*> instead of a vector. Otherwise you would have to linearly search for the target to erase it. Not to mention erasing something from a vector also has linear computational complexity.

Does a set allow me to iterate trough its contents linearly? I want my node-objects to have a set of children which is linearly ordered, but I also want to easily access the individual elements by its value. I may be too used to the simplicity of Python, but I sure hope I can do this easily in C++ too.
And by the way, thank you for the answer!

Lexical Unit
Sep 16, 2003

Sure. The google search you're looking for is "iterators". Modifying your code for example:
code:
for (set<node*>::iterator i = children.begin (); i != children.end(); ++i) {
    cout << (*i)->name << ", ";     
}

clearly not a horse
May 8, 2009

undue butt brutality is not a criminal offense

Lexical Unit posted:

Sure. The google search you're looking for is "iterators". Modifying your code for example:
code:
for (set<node*>::iterator i = children.begin (); i != children.end(); ++i) {
    cout << (*i)->name << ", ";     
}

Thanks again for the answer. I see I've got quite a bit to get used to, especially the quirks in the syntax. I tried that code and I do not get any syntax errors - but when I wrote it I wrote i*, (i*) and got a syntax error, but I don't get the distinction.

When I declare an iterator inside a for-loop, does the i point to the object based on where in the sequence it is?

I try to use my "print()" function to make the program tell me the names of the members of the child-elements, but I do not get the answer I want - I do not get any answer at all. (I substituted all my for-loops to correspond to your snippet.)

Vanadium
Jan 8, 2005

clearly not a horse posted:

when I wrote it I wrote i*, (i*) and got a syntax error, but I don't get the distinction.

What. *i is right, i* is wrong. * is an unary operator here and you put it before its operand.

quote:

When I declare an iterator inside a for-loop, does the i point to the object based on where in the sequence it is?

It is not defined that they do. But they have an operator* that returns a suitable reference. I am not sure what you mean by "based on where it is", but operators get invalidated under certain conditions, depending on what iterator it is. I think iterators of sets stay valid until you remove the object they refer to from the set, or something.

quote:

I try to use my "print()" function to make the program tell me the names of the members of the child-elements, but I do not get the answer I want - I do not get any answer at all. (I substituted all my for-loops to correspond to your snippet.)

So what did you get?

Mr.Radar
Nov 5, 2005

You guys aren't going to believe this, but that guy is our games teacher.

Le0 posted:

I tried to do what you explained but yes it is not possible.
How should I fix this issue correctly ?

If I read your post correctly, your problem boils down to:
code:
/* file1.h */
#include "file2.h"
struct f1struct {};
class f1class {
    f2struct var;
};

/* file2.h */
#include "file1.h"
struct f2struct {};
class f2class {
    f1struct var;
};
If this is the case then the only solution would be to break up file1.h and file2.h so that the structures and classes are defined in separate files:
code:
/* f1struct.h */
struct f1struct {};

/* f2struct.h */
struct f2struct {};

/* f1class.h */
#include "f2struct.h"
class f1class {
    f2struct var;
};

/* f2class.h */
#include "f1struct.h"
class f2class {
    f1struct var;
};

Sweeper
Nov 29, 2007
The Joe Buck of Posting
Dinosaur Gum
Where do you guys declare your variables? I always declare them at the top of the block they are used in, but someone was telling me that proper style dictates that you declare them where you first use them?

Vanadium
Jan 8, 2005

I declare them whereever I want the constructor to run. :v:

For variables of types with trivial constructors, I tend to declare stuff as late as possible. Sometimes that lets me make them const if it turns out I am not assigning anything else to them later. I am not sure whether that is a good argument.

MrMoo
Sep 14, 2000

Sweeper posted:

Where do you guys declare your variables? I always declare them at the top of the block they are used in, but someone was telling me that proper style dictates that you declare them where you first use them?

C89 style is at the head of the block, C99 and common sense style is to declare them close to where you use them. Any good compiler will automatically move the storage to the correct place and declaring later gives better hints to the compiler about the scope and lifetime.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
The point of a variable is to hold information. A variable that isn't holding useful information is useless, unless it is about to initialized with useful information. Therefore, scope is a powerful tool to communicate what information is currently useful. Ideally, you want variables to be in scope only when they contain meaningful information; they should enter scope when they're initialized with useful data, and they should exit scope when they cease to contain useful data (†). The extent to which your code follows this maxim is the extent to which you can trust your local variables to contain meaningful data when you revisit the function later.

† In C/C++, making variables leave scope when they become useless can be awkward to actually achieve outside of some specific examples like if conditions and loop initializers. Still.

Avenging Dentist
Oct 1, 2005

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

MrMoo posted:

C89 style is at the head of the block, C99 and common sense style is to declare them close to where you use them. Any good compiler will automatically move the storage to the correct place and declaring later gives better hints to the compiler about the scope and lifetime.

Huh? I'm pretty sure most compilers will only create activation records at the function level, not at the block level (and certainly not on a per-declaration level), in order to minimize manipulation of the stack frame. The only thing that really matters, aside from determining when you want constructors to run, is putting declarations in parallel blocks to minimize the size of the activation record for that function.

rjmccall posted:

† In C/C++, making variables leave scope when they become useless can be awkward to actually achieve outside of some specific examples like if conditions and loop initializers. Still.

It's not awkward if you really love curly braces!

Sweeper
Nov 29, 2007
The Joe Buck of Posting
Dinosaur Gum

Avenging Dentist posted:

Huh? I'm pretty sure most compilers will only create activation records at the function level, not at the block level (and certainly not on a per-declaration level), in order to minimize manipulation of the stack frame. The only thing that really matters, aside from determining when you want constructors to run, is putting declarations in parallel blocks to minimize the size of the activation record for that function.


It's not awkward if you really love curly braces!
So do most people program by declaring right before use or can I keep my stuff all at the top in an easy to find place (for me, also I am weird and I like it more to separate actions)? Also can you explain the parallel blocks thing? I tried googling it but didn't get much back, I don't think.. I couldn't really tell.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
code:
void foo()
{
    {
        int i;
        int j;
    }

    {
        int k;
    }
}
These are two parallel blocks. You could also call them mutually-exclusive or whatever. The activation record for this function would be 2 ints big (plus space for the return address and so forth).

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Avenging Dentist posted:

It's not awkward if you really love curly braces!

And why even be a C programmer if you don't really love curly braces? Every day I thank the gods that C++0x is giving us that many more opportunities to express our affection for this glorious form of delimiting punctuation.

Sweeper
Nov 29, 2007
The Joe Buck of Posting
Dinosaur Gum

Avenging Dentist posted:

code:
void foo()
{
    {
        int i;
        int j;
    }

    {
        int k;
    }
}
These are two parallel blocks. You could also call them mutually-exclusive or whatever. The activation record for this function would be 2 ints big (plus space for the return address and so forth).
Oh so because it can use a maximum of 2 ints at a time kind of thing? Do people program like that, with the blocks I mean. I've never seen it, but I haven't programmed in C++ much and I'm still in college so I haven't seen too much real world stuff yet.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
We need better keyboards. Surely the future of programming is the addition of extra-curly braces.

Sweeper posted:

Oh so because it can use a maximum of 2 ints at a time kind of thing? Do people program like that, with the blocks I mean. I've never seen it, but I haven't programmed in C++ much and I'm still in college so I haven't seen too much real world stuff yet.

No, but imagine those were two if statements, or for loops, or what-have-you. (You might do something like that if you were using scoped locks, but let's not get into that.)

Sweeper
Nov 29, 2007
The Joe Buck of Posting
Dinosaur Gum

Avenging Dentist posted:

We need better keyboards. Surely the future of programming is the addition of extra-curly braces.


No, but imagine those were two if statements, or for loops, or what-have-you.
Alright, should I change my style and declare before use or does it not really matter? Do most people declare before use? I don't know where I learned to declare everything at the top of a block.

MrMoo
Sep 14, 2000

Avenging Dentist posted:

Huh? I'm pretty sure most compilers will only create activation records at the function level, not at the block level (and certainly not on a per-declaration level), in order to minimize manipulation of the stack frame.

If we're talking basic C data types the compiler can keep a variable in a register and never have to move the stack. The location of declaration can help determine whether a variable should be memory or register based.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
In old versions of C it used to be required, so there's a fair amount of code that still follows that convention. Undoubtedly there also exist people who believe this is in some way a good practice. It's not. You should declare variables when initializing them if at all possible, or as close as possible to that point if not.

OddObserver
Apr 3, 2009

MrMoo posted:

If we're talking basic C data types the compiler can keep a variable in a register and never have to move the stack. The location of declaration can help determine whether a variable should be memory or register based.

And spill slots can be overlapped as well, as long as their live ranges are distinct. Though, it is an issue of quality of implementation, of course.

Avenging Dentist
Oct 1, 2005

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

MrMoo posted:

The location of declaration can help determine whether a variable should be memory or register based.

Why would an optimizer look at the position of local declarations of primitives or PODs instead of where usage actually occurs? I can think of nothing in either the C or C++ specs that would affect that. Honestly, even putting stuff in parallel blocks probably isn't necessary for primitives/PODs.

Avenging Dentist fucked around with this message at 03:17 on Jun 5, 2010

Brecht
Nov 7, 2009

Sweeper posted:

So do most people program by declaring right before use or can I keep my stuff all at the top in an easy to find place (for me, also I am weird and I like it more to separate actions)?
(IMO) you should break yourself of this habit; it's a bad practice to declare stuff in this way when you don't have to. It wouldn't pass a code review from me.

emf
Aug 1, 2002



Brecht posted:

(IMO) you should break yourself of this habit; it's a bad practice to declare stuff in this way when you don't have to. It wouldn't pass a code review from me.
In which way? Right before use or at function start?

edit: VV Cool. Thanks for the clarification. That what I usually do, but I probably wouldn't pass a code review either.

emf fucked around with this message at 21:58 on Jun 5, 2010

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
If you have the ability to declare at the point of use (i.e. you're not using C89), you should. You certainly shouldn't ever declare everything at the start of a function, not even in C89.

Sweeper
Nov 29, 2007
The Joe Buck of Posting
Dinosaur Gum
Alright thanks guys :)

clearly not a horse
May 8, 2009

undue butt brutality is not a criminal offense
I have a question regarding inclusion and header files. I have been trying to find some good info on this, also from Bruce Eckels Thinking in C++, but I cannot find anything that resembles an answer for me yet, even there.

Say I have a class "A" stored in "a.cpp" and a class "B" stored in "b.cpp".
Each of these classes has a pointer or function or something which is dependent on the other.
I know from recent experience that I cannot simply include a.cpp in b.cpp and vice versa, because that made my computer cry.

How can I get around this problem?

Vanadium
Jan 8, 2005

you include hpp files anyway
use forward declarations and pointers or references and header files and you should be fine

clearly not a horse
May 8, 2009

undue butt brutality is not a criminal offense

Vanadium posted:

you include hpp files anyway
use forward declarations and pointers or references and header files and you should be fine

Thanks for the answer, but I am quite a dummy. C++ is new to me. (So is programming to an extent.) I should be able to read up on it with the right keyword in the back of my head.
But if I may ask one more favour here, I also have a problem with inheritance and the constructors.

http://codepad.org/ag9JeJYI

At line 144, I get a compilation error. Something about the constructor of a derived class.

Adbot
ADBOT LOVES YOU

seiken
Feb 7, 2005

hah ha ha
The derived class needs to construct the base class, and the base class does not have a no-argument constructor. The compiler has no way of knowing that you intend both of the string tname parameters to be the same thing. You need to replace that line with something like
code:
lexicalnode (string tname) : node(tname) {}
explicity calling the base-class constructor.

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