Jump to content
  • Advertisement
Sign in to follow this  
ZwodahS

A simple C++ question

This topic is 2116 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I really want to google this question but I don't even know what to search

class Foo
{
    enum Value
    {
        One,
        Two,
    } value;

    struct Data
    {
       int x;
       int y;
    } data;
};

I am just wondering if there is any consequences and any things that I need to take note of when I do them ? 

To be honest, I don't really know what is the different between that and

class Foo
{
    enum Value
    {
        One,
        Two,
    };
    Value value;

    struct Data
    {
       int x;
       int y;
    };
    Data data;
};

Can anyone tell me what this thing is , and also point me in the direction to learn more about it. I can always do (and has always been doing) the second one but I accidentally typed the first piece of code and it works, and I am wondering why.

Edited by ZwodahS

Share this post


Link to post
Share on other sites
Advertisement

It's a hangover from C, and it is also the reason class, enum and struct definitions need to end with a semicolon, a source of many cryptic compiler errors.

 

Originally in C you had to do

 

struct { int x; int y; } data;

 

then to simplify things (so you can declare other variables with the same type in multiple locations without having to copy/paste, which is a maintenance nightmare) you could use a typedef, this was added more as an afterthought really though ;)

 

typedef struct { int x; int y; } MyStruct;

 

but if you wanted a pointer to said struct inside the struct (e.g. for a linked list) you had to use a "tag" to identify the struct

 

typedef struct MyStructTag { struct MyStructTag* pMyStruct; int x; int y; } MyStruct;

 

Then C++ came along and (rightly) decided the typedef was unnecessary, but all the above forms are also allowed in C++ for backwards compatibility.

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites

Thanks for pointing me to where to search for all the information biggrin.png

Just to confirm my "findings", there is no differences in the 2 code that I pasted in the original post.
However,

struct Foo
{
    int x;
} foo;

typedef struct Foo
{
    int x;
} foo;

these are different.

 

So what are the cases that we need/should use typedef ? I don't see the need to use typedef so far. I know people like to use typedef to hide the underlying implementation of the data type, like "typedef int score" for example, so they can change it to long in the future if they want. However, I prefer to know exactly what that thing is, so I tend not to use typedef. So is there any uses for typedef that I don't know ? 

Edited by ZwodahS

Share this post


Link to post
Share on other sites

Thanks for pointing me to where to search for all the information biggrin.png

Just to confirm my "findings", there is no differences in the 2 code that I pasted in the original post.
However,

struct Foo
{
    int x;
} foo;

typedef struct Foo
{
    int x;
} foo;

these are different.

 

So what are the cases that we need/should use typedef ? I don't see the need to use typedef so far. I know people like to use typedef to hide the underlying implementation of the data type, like "typedef int score" for example, so they can change it to long in the future if they want. However, I prefer to know exactly what that thing is, so I tend not to use typedef. So is there any uses for typedef that I don't know ? 

In C++, you'd never need to use a typedef like that. C added typedefs because without it, you have to do:

struct Foo
{
    // ...
};
 
struct Foo foo; // everytime you want to use Foo, you must prefix it with "struct"

 

Prefixing everything with "struct" gets annoying, so this is common in C:

typedef struct Foo
{
    // ...
} Foo;
 
Foo foo; // now "struct" is no longer necessary!
 
// Note, some people do the following:
typedef struct Foo
{
    // ...
} Foo_t;
 
Foo_t foo; // so "Foo" is the original struct (needs "struct" prefix if you use it), and "Foo_t" is the simplified typedef (does not need "struct" prefix)

 

In C++, this isn't an issue, because when you define a struct, you don't have to prefix the type name with "struct" every time you want to use it like you do in C. So you don't typedef things like this in C++. But typedef is still used in C++. It can be used to simplify a really long type name:

std::map<std::string, std::vector<std::string>>::const_iterator myIterator; // Holy crap that's a long type name
 
// Or we can simplify it:
typedef std::map<std::string, std::vector<std::string>>::const_iterator my_const_iterator;
my_const_iterator myIterator; // Now we get to use the short/simplified type name!

 

There are other times typedef is useful in C++. Sometimes it's useful for each class to define some kind of type name that can be used in generic template code. For example, std::vector, std::deque, and std::list all define a bunch of "Member Types", all of which are just typedefs for some underlying type. This means I can write the following function:

// A silly example, but it shows the idea
template <typename DataStructureType>
typename DataStructureType::value_type getFirstElement(const DataStructureType& dataStructure)
{
    return dataStructure.front();
}
 
// Now I can call that function with a std::vector, std::deque, std::list, or pretty much anything else that
// has a proper value_type typdef and a front() member function. This would not be possible without
// a typedef.

Share this post


Link to post
Share on other sites

Yes, those 2 are different, in the second "foo" is the name of the typedef and struct Foo is the tag you use if you need declare a pointer to the struct inside the struct. typedef is unnecessary for struct/enum/class in C++ but see Cornstalks post above.

 

EDIT: Note, in C, Cornstalks example of using

 

typedef struct Foo { ... } Foo_t;

 

does not allow you to use Foo_t pointers inside the struct, since the compiler sees the Foo_t* before it has parsed the typedef name.

 

EDIT2: Also in C, if you accidentally forget the typedef and do this:

 

struct Foo { ... } Foo;

 

you end up with a variable of type struct Foo that is called Foo, so wastes space (discovered this on a PS1 game where memory was tight!). The struct names namespace and the global namespace are different and you can have the same identifier name for different objects (EDIT: by objects, I mean "compiler objects" as in struct definitions, variable defintions, etc., not objects in the C++ sense,  which are really just instances of a type). I think that would produce an error in C++?

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites

I think that would produce an error in C++?

Interestingly, it does not. So what does it do? It creates a variable that you can use. You can think of it as a form of shadowing (like how you can declare a new local variable with the same name as a previous variable in an outer scope). If you try to use it as a type name it's an error (what I consider to be a simpler example). You can kind of get around the issue, though.

 

This SO Q&A is worth a read.

Share this post


Link to post
Share on other sites

So that behaviour is the same in C and C++, presumably for backward compatibility reasons. (And again, the reason is that the type names namespace and the global namespace [and all other namespaces in C++] are different).

 

EDIT: In simpler terms, the development of C++ from C was akin to trying to make an octopus by nailing an extra 4 legs onto a dog.

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites

The confusing thing is that there are 2 different ways to use struct names in C,

 

typedef struct { int x; int y; } TypedefedAnonymousStruct;

 

struct MyStruct { int x; int y; };

 

and they are used slightly differently (in C only, not in C++, although you can prefix the name with struct if you like in C++), as Cornstalks pointed out

 

TypedefedAnonymousStruct myVariable;

struct MyStruct myOtherVariable;

 

however if you need a pointer to the struct within the struct you must use the non-typedef version, and the typedef version allows you to specify a tagname too, which can be different to the typedef name if you want.

 

And add to that the ability to immediately declare a variable of the type like so

 

struct { int x; int y; } data;

 

which you can't do with the typedef version (which is the cause of the required semicolon at the end of class/struct/enum definitions). Note you can't do that in C# and Java so semicolons after the definition are not required there.

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!