Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 703 704 [705] 706 707 ... 796

Author Topic: if self.isCoder(): post() #Programming Thread  (Read 890083 times)

McTraveller

  • Bay Watcher
  • This text isn't very personal.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10560 on: May 14, 2017, 12:04:27 pm »

All members of a class are accessible to the implementation of that class - so if you have something like
Code: [Select]
class Foo
{
   large_struct_t large_struct;

   public void doSomething(Foo& otherFoo)
   {
        otherFoo.large_struct; // completely fine
   }
}
Logged
This product contains deoxyribonucleic acid which is known to the State of California to cause cancer, reproductive harm, and other health issues.

DeKaFu

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10561 on: May 14, 2017, 01:42:31 pm »

Okay, I think I get it.

So in my case, it would just be a matter of passing the two parent-instances by reference to a constructor of the child-instance?
like
Code: [Select]
foo a;
foo b;

foo c(a,b);

with the constructor for foo c looking like
Code: [Select]
foo::foo(foo& foo_instance, foo& bar_instance){

    (function that looks at foo_instance.bigstruct and bar_instance.bigstruct and uses them to write to bigstruct)
}

...right?

And if I put "const foo& foo_instance" instead, it would work the same while also preventing the child's function from accidentally modifying anything belonging to the parent instances, correct?
Logged

Spehss _

  • Bay Watcher
  • full of stars
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10562 on: May 18, 2017, 10:24:31 am »

Minor question.

In C++, if I have some functions I want to define and use in a project, what's the "proper" way of saving them? Header files or cpp files? Header files are for class definitions and cpp files are for defining the methods of the class, so just functions with no class would go in cpp files, right?
Logged
Steam ID: Spehss Cat
Turns out you can seriously not notice how deep into this shit you went until you get out.

Antsan

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10563 on: May 18, 2017, 10:27:40 am »

You'd put the function declaration into the hpp header and the function implementation into the corresponding cpp file. Functions implemented in headers are automatically inlined, as far as I know.
Logged
Taste my Paci-Fist

alway

  • Bay Watcher
  • 🏳️‍⚧️
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10564 on: May 19, 2017, 02:07:05 am »

This is c++; there's nothing 'automatic' about header files. When you do
Code: [Select]
#include "somefile.h"
when the compiler preprocessing runs through, it sees that, loads up somefile.h, then essentially copies the text and pastes it all right there.

Related, you use 'include guards' for most complex programs with either
Code: [Select]
#pragma once
// file contents
or some variant of
Code: [Select]
#if !defined( SOMEFILE_H )
#define SOMEFILE_H
// file contents
#endif
Since that copy-paste doesn't know if it's already happened before in that file. For example, if you had somefile.h and someotherfile.h, where someotherfile.h has an #include "somefile.h" and then you had a cpp file doing
Code: [Select]
#include "somefile.h"
#include "someotherfile.h"
You end up with 2 sets copied in without the include guards, which is then compiled, and probably complains about multiple copies of the same definitions. It's a very simple model of copy-pasting file contents, and so is quite easy to reason about.

When the compiler step runs, after doing the #include copy-pastes and some other things in preparation for the compile, it specifically is compiling the .cpp files into intermediate files one by one, with each file 100% independent and without reference to any other .cpp files anywhere. (this is also why compiling is extremely multi-core friendly) During this step, it builds up a list of references from everything that's been declared previously (so it knows it isn't just a syntax error/type) as essentially a "TODO: figure out where these things are" This stuff goes into the .obj files you probably noticed your compiler producing as an intermediate byproduct.

Then the linker runs and combines all the .obj and library files into the final program; it takes those symbol references and resolves them by looking around for a definition that provides all the necessary information.

As for what's necessary for these steps:
For the compiler, it does basic syntax matching as well as static memory allocation related stuff.
Code: [Select]
MyClass A; // This line fails to compile because MyClass is assumed to be a typo, since you never told it MyClass is some sort of symbol.
Foo(); // This line fails to compile for the same reason.

class MyClass;    // declare the class without defining it; "there is a symbol called MyClass"
void Foo( int ); // declare the function without defining it; "there is a function called Foo which returns void and takes int as a parameter"

MyClass B; // This line fails to compile because MyClass is 'undefined' which means the compiler now knows it is a type symbol, but it doesn't know how big it is, and thus it can't figure out how much memory needs to be allocated here.
MyClass* C; // This line compiles just fine because it knows MyClass is a type, and it knows C is a pointer, which has a known size of 32/64 bits depending on platform. Memory allocation of a thing pointed to (if it ever occurs) happens elsewhere, so the compiler doesn't complain.
MyClass& D; // This line fails to compile because references need to be initialized to refer to something; but as shown in B, a mere declaration can't be used to create something to refer to, so these are out too.
Foo( 1 ); // This line compiles correctly because it knows Foo is a function symbol. Because calling a function requires no allocated memory, the compiler is entirely fine with this.

class MyClass  // define MyClass symbol to mean 'a class consisting of an int member'
{
   int a;
};

MyClass E; // This line compiles; after processing the previous line, the compiler now knows MyClass is a specific size, and so can allocate space for the variable E
MyClass& F = E; // Likewise, this compiles (of course) since we now have a value to reference.
Again, remember back to how header files work: just a copy-paste. So any of the preceding code could be moved into a header file and #include "thatheaderfile.h" used to copy them back in. (Side note: You can in fact copy any arbitrary code ((even inside of functions! even in the middle of a line!)) into a header file such that you just have some random code bits sitting out in the open in a .h file. If you ever do this in the workplace, you will be rightfully drawn and quartered, then hung in the four corners of the office as a warning to the rest. So yes, it really does behave like a copy-paste of a file's contents) Also of note, when the compiler runs through doing these things, it's scanning from top to bottom. This is why when you include a header file from a library, it needs to be above where it is used, and so by convention they are all dropped at the top of the file.

Then there's the linker that runs after the compile phase has made them into the compiled .obj files which links them all together. Taking the above example, all of the parts that compiled correctly would link correctly *except* for the call to Foo(). If, however, we had other .cpp files in the project and one of those .cpp files held the definition of Foo like:
 void Foo( int a ) { return; }
the linker would successfully find the definition of the Foo symbol, without the need for the copy-paste which is .h file includes; otherwise the result would be a linker error reporting an 'undefined symbol Foo'


So in summary, things that go into header files:
1. Declarations of things you want the compiler to recognize as a symbol to link, rather than thinking it's a typo/syntax error. (externally visible functions, class member functions)
2. Definitions of things you want to be able to create instances of non-dynamically. (classes usually)
3. Templates -- not mentioned above, but it needs to figure this out at compile time, since it needs to figure out how much code to generate, which falls under category 2's broad 'memory stuff'.
Hopefully that gives you a broad overview for reasoning about declaration/definition of stuff as it relates to header files and C++'s code building system.
« Last Edit: May 19, 2017, 02:09:31 am by alway »
Logged

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10565 on: May 19, 2017, 02:16:55 am »

You'd put the function declaration into the hpp header and the function implementation into the corresponding cpp file. Functions implemented in headers are automatically inlined, as far as I know.

What alway said. #include in c/c++ is literally nothing more than a copy/paste macro.

To show that's the case you can literally #include parts of commands, and they get cut/paste into where you want them:

Code: [Select]
#include <iostream>

int main()
{
std::cout <<
#include "message.h"
<< std::endl;

std::cin.get();
return 0;
}

message.h:

"hello world"

e.g. if you have a csv (comma separated values) file then you could feed it into a function that takes a variable number of arguments just using the #include macro (but it will always have the values that existed when you compiled it, not at runtime).

This explains the most common confusion about header files - why the compiler spits the dummy unless you use inline , static or extern. If you have normal stuff in a header that's used by two or more cpp files, it's copied verbatim into every one of those cpp file at compile time, causing you to have multiple variables/functions with the same name at the global scope.

Inline, static and extern functions fix the multiple-reference issue from sharing header files:

- static functions are only visible inside the same translation unit (cpp file), so if you make a static function in a header, it's implemented separately in each cpp file. This of course causes unnecessary bloat.

- inline functions are compiled right into the calling code, so they avoid function overhead and remove the function call / name completely, meaning there's no conflict there. But it can also cause code bloat, since the entire code for the function is replicated each time you use it.

- extern means for the code to search for the function in a different cpp file, this is the preferable way if you want to avoid the code bloat that's possible with the other two ways to share a function, it's also the best practice since changing the implementation won't cause all cpp files to need to be recompiled.

If you decided to go for functional programming in c/c++, rather than object-oriented programming, which is a perfectly legitimate choice, then you should heavily use "extern" keyword in your header files, for sharing functions between cpp files. it's the equivalent to using classes but hiding the implementation in the cpp file.
« Last Edit: May 19, 2017, 02:38:01 am by Reelya »
Logged

lethosor

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10566 on: May 19, 2017, 09:49:46 am »

If you decided to go for functional programming in c/c++, rather than object-oriented programming, which is a perfectly legitimate choice, then you should heavily use "extern" keyword in your header files, for sharing functions between cpp files. it's the equivalent to using classes but hiding the implementation in the cpp file.
"extern" is the default for functions in C/C++, so you don't need to specify it explicitly (and doing so is likely to confuse people, anyway). That assumes the definition is in a source (.cpp) file, of course.
Logged
DFHack - Dwarf Manipulator (Lua) - DF Wiki talk

There was a typo in the siegers' campfire code. When the fires went out, so did the game.

RoguelikeRazuka

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10567 on: May 23, 2017, 05:29:22 pm »

Just a quick question about C.
Is there any difference between

Code: [Select]
typedef enum {A, B, C} enum1;
and

Code: [Select]
typedef enum enum1 {A, B, C};
in how the compiler would treat it?
I mean, which of the above is the right declaration of a "custom" enum type with the typedef statement?
« Last Edit: May 23, 2017, 05:32:27 pm by RoguelikeRazuka »
Logged

da_nang

  • Bay Watcher
  • Argonian Overlord
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10568 on: May 24, 2017, 12:13:06 pm »

Just a quick question about C.
Is there any difference between

Code: [Select]
typedef enum {A, B, C} enum1;
and

Code: [Select]
typedef enum enum1 {A, B, C};
in how the compiler would treat it?
I mean, which of the above is the right declaration of a "custom" enum type with the typedef statement?

Code: (test.c) [Select]
#include <stdio.h>

int main(int argc, char** argv) {
typedef enum {A, B} Foo;
typedef enum Bar {C, D};

Foo f = A;
Bar b = D;
printf("Foo: %d\n", f);
printf("Foo: %d\n", b);

return 0;
}

The above compiles and runs fine with g++ but line 5 raises a warning, stating that typedef is ignored.

The same warning is raised in gcc but fails to compile with an error raised on line 8.

Moral of the story: Use the first one.
Logged
"Deliver yesterday, code today, think tomorrow."
Ceterum censeo Unionem Europaeam esse delendam.
Future supplanter of humanity.

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10569 on: May 24, 2017, 01:40:29 pm »

The warning on line 5 is because "enum {A, B}" is a whole type, and "enum Bar {C, D}" is also a whole type. One is a unnamed enum, the other is a named enum. So the 2nd one was just read as a typedef with the end name missing. This will actually work:

Code: [Select]
typedef enum Bar {C, D} Bar2; // define Bar2 as an alias for enum Bar
The compiler error on line 8 is because you have to write "enum Bar" in C for named enums. In C++ they changed that. The typedef trick is popular because it lets you omit the word enum from type usages, but in a C and C++ compatible way.

note that C++ brought in type safety for enums. There's no type checking for enums whatsoever in C:

Code: [Select]
typedef enum { A, B} Foo;
enum Bar { C, D};

enum {} f = A;
f = B;
f = C;
f = D;
f = 3;

Foo f2 = A;
f2 = B;
f2 = C;
f2 = D;
f2 = 3;

int f3 = A;
f3 = B;
f3 = C;
f3 = D;
f3 = 3;

        enum Bar b = A;
        b = B;
        b = C;
        b = D;

Stick to C++ style type enforcing however for enums, because it's a better practice, even though C doesn't enforce it.
« Last Edit: May 24, 2017, 01:58:30 pm by Reelya »
Logged

Spehss _

  • Bay Watcher
  • full of stars
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10570 on: May 30, 2017, 08:34:08 pm »

So I'm making a class that has a private data member which is itself a class. I'm trying to set it up so that the class can return a pointer to the member class so that the public accessor/mutator methods of the member class can be called in the client with this kind of function call: ClassA.getClassB.setClassBMember(foo)

I've done this before in another IDE where the value returned by the function that returns a pointer/memory address was a pointer to an array. It worked and it works in the current IDE I'm using, Visual Studio. If I remember right it was Reelya that suggested this.

Trying to set up something similar where the return value is a pointer/memory address to a single class rather than an array of classes, and the compiler is giving me errors and I'm not sure how to fix it. I don't entirely understand how the working code actually works so  don't know how to troubleshoot why the second code isn't working.

I thought I could fix it by making a pointer and return the pointer instead of the memory address of the member class object but that doesn't work.

Spoiler: working code (click to show/hide)

Spoiler: not working code (click to show/hide)

Help please?
Logged
Steam ID: Spehss Cat
Turns out you can seriously not notice how deep into this shit you went until you get out.

Spehss _

  • Bay Watcher
  • full of stars
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10571 on: May 30, 2017, 09:02:19 pm »

Disregarding the technical issue, what exactly do you intend on accomplishing, here? You have a private member variable for which you want a public function to return the address to this variable, so how is the variable still private? The whole point of encapsulation is that all alterations to internal variables of a class must happen through structures controlled by the class object itself. If I can just pull an address of an internal variable through a public function, then I would never need to use it again because I can just alter said internal variable directly through that address.
Mostly to save me the hassle of writing additional methods for classes that will contain an instance of CoordinatePair() where these methods would just be calling CoordinatePair methods.

yknow when you put it like you did, what I was thinking of doing just seems stupid. I can just make higher level functions manipulating the object. I don't think I thought this through completely.
Logged
Steam ID: Spehss Cat
Turns out you can seriously not notice how deep into this shit you went until you get out.

Parsely

  • Bay Watcher
    • View Profile
    • My games!
Re: if self.isCoder(): post() #Programming Thread
« Reply #10572 on: May 30, 2017, 10:17:42 pm »

Mostly to save me the hassle of writing additional methods for classes that will contain an instance of CoordinatePair() where these methods would just be calling CoordinatePair methods.

yknow when you put it like you did, what I was thinking of doing just seems stupid. I can just make higher level functions manipulating the object. I don't think I thought this through completely.
Don't feel embarrassed, these things happen.
Logged

alway

  • Bay Watcher
  • 🏳️‍⚧️
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10573 on: May 31, 2017, 03:34:19 am »

To put it mildly, yeah. 90% of programming is having no idea what you're doing. If you said you could fully think through all your designs and all their side effects before implementing it, I would hand you a stack of a dozen bug reports resulting from subtle oversights the last time you said that. A lot of it comes down to accepting that the act of implementing designs is a part of the design process itself; and that things always look entirely straightforward up until the point at which you realize a fatal or troublesome design flaw. You will never think things through completely because your brain can't generally handle a complex program in its entirety from memory in the wishy-washy abstract brainspace. In cases where you can, it's generally because you explored the space thoroughly in a previous iteration or project.
Logged

EnigmaticHat

  • Bay Watcher
  • I vibrate, I die, I vibrate again
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10574 on: June 01, 2017, 04:09:43 pm »

Can we use this thread to talk about stuff we're doing we think is cool?
Spoiler: if not I'll spoiler it (click to show/hide)
Logged
"T-take this non-euclidean geometry, h-humanity-baka. I m-made it, but not because I l-li-l-like you or anything! I just felt s-sorry for you, b-baka."
You misspelled seance.  Are possessing Draignean?  Are you actually a ghost in the shell? You have to tell us if you are, that's the rule
Pages: 1 ... 703 704 [705] 706 707 ... 796