• C++ Vector pointers
    53 replies, posted
There are two errors in your code. The first is what people have said: Vector2D is only known and exclusive to pieceMain. You should move Vector2D into a separate file. The other error is your ampersand. When you call: [cpp]pieceMain.setPiecePos(&coords[i]);[/cpp] You're saying "get the address of the i'th index of coords." To use references, you use the ampersand in the function declaration. So instead of: [cpp]void pieceMain::setPiecePos(Vector2D)[/cpp] You write: [cpp]void pieceMain::setPiecePos(Vector2D &pos)[/cpp] Which means, "a reference of Vector2D" to the function. To call the new function declaration, you simply write: [cpp]pieceMain.setPiecePos(coords[i]);[/cpp]
[QUOTE=st_nick5;36473415]Well, that's what I was taught, and they work.[/QUOTE] Stick to it. Your teacher is right. Pragmas are non-standard (even though 'once' will work on some compilers), and #define is the proper way to do this. Once you start going down the shitty non-standard path, there's no telling when you'll stop and how long it will take for you to recover and shovel all the bullshit back out of your brain. I'm fairly certain KillerJaguar nailed it. Your parameter was a Vector2D and you were passing a reference to a Vector2D. There were other minor issues but that seemed like it.
[QUOTE=KillerJaguar;36473643]There are two errors in your code. The first is what people have said: Vector2D is only known and exclusive to pieceMain. You should move Vector2D into a separate file. The other error is your ampersand. When you call: [cpp]pieceMain.setPiecePos(&coords[i]);[/cpp] You're saying "get the address of the i'th index of coords." To use references, you use the ampersand in the function declaration. So instead of: [cpp]void pieceMain::setPiecePos(Vector2D)[/cpp] You write: [cpp]void pieceMain::setPiecePos(Vector2D &pos)[/cpp] Which means, "a reference of Vector2D" to the function. To call the new function declaration, you simply write: [cpp]pieceMain.setPiecePos(coords[i]);[/cpp][/QUOTE] Just tried that as well. Got an error log: [quote] 1>c:\users\nicholas\documents\chess set\2dchess\2dchess\chess\vector2d.h(1): error C2011: 'Vector2D' : 'struct' type redefinition 1> c:\users\nicholas\documents\chess set\2dchess\2dchess\chess\vector2d.h(1) : see declaration of 'Vector2D' 1>c:\users\nicholas\documents\chess set\2dchess\2dchess\chess\board.cpp(86): error C2079: 'xycoords' uses undefined struct 'Vector2D' 1>c:\users\nicholas\documents\chess set\2dchess\2dchess\chess\board.cpp(102): error C2228: left of '.x' must have class/struct/union 1> type is 'int' 1>c:\users\nicholas\documents\chess set\2dchess\2dchess\chess\board.cpp(103): error C2228: left of '.y' must have class/struct/union 1> type is 'int' 1>c:\users\nicholas\documents\chess set\2dchess\2dchess\chess\board.cpp(106): error C2664: 'void std::vector<_Ty>::push_back(_Ty &&)' : cannot convert parameter 1 from 'int' to 'Vector2D &&' 1> with 1> [ 1> _Ty=Vector2D 1> ] 1> Reason: cannot convert from 'int' to 'Vector2D' 1> Source or target has incomplete type 1> Generating Code... 1> Compiling... 1> main.cpp 1> Generating Code... 1> Compiling... 1> piece.cpp 1>c:\users\nicholas\documents\chess set\2dchess\2dchess\chess\piece.cpp(52): error C2511: 'void pieceMain::setPiecePos(Vector2D)' : overloaded member function not found in 'pieceMain' 1> c:\users\nicholas\documents\chess set\2dchess\2dchess\chess\piece.h(6) : see declaration of 'pieceMain' 1> Generating Code... 1> 1>Build FAILED. [/quote] The initPlacement() function doesn't recognise the coords vector, and there's also a problem with .push_back in the setCoords() function. The dot is underlined. edit - In fact, it looks like it does recognise the coords vector, the error message is: "a reference of type "Vector2D &" (not const-qualified) cannot be initialized with a value of type "Vector2D".
[QUOTE=flayne;36473480]I don't think you understand what push_back does. Based on your error log there it appears you tried to call push_back(1). You most likely think this adds one new element to the vector but its designed to add the variable (of which should be used in place of 1) to the end of the vector.[/QUOTE]
[QUOTE=flayne;36482364][/QUOTE] Not entirely sure what you mean. I've already added all the elements I need to the vector. What I'm trying to do is find element i and send it to the setPiecePos() function in the pieceMain class.
The core problem you seem to be having is that Vector2D is either: Vector2D is defined somewhere else, like as a private subclass you originally had; or you're not placing header guards, causing header files to be read multiple times. [quote]error C2664: 'void std::vector<_Ty>::push_back(_Ty &&)' : cannot convert parameter 1 from 'int' to 'Vector2D &&[/quote] The reason it says that is because Vector2D is undefined, and therefore automatically assumes a struct/class it doesn't know to be an int. [quote]error C2511: 'void pieceMain::setPiecePos(Vector2D)' : overloaded member function not found in 'pieceMain'[/quote] You're also getting another error in the function definition (.cpp file), where you forget the & in the function signature.
I think I might have fixed it. I was linking to the Vector2D.h file in the .cpp files, and once I linked to it in the .h files instead, it compiled. Thanks a lot for your help, gonna go test this out now. edit - It is working. Success! Been at this for nearly a week. Now I can finally carry on with coding. Thanks guys!
[QUOTE=gparent;36478021]Stick to it. Your teacher is right. Pragmas are non-standard (even though 'once' will work on some compilers), and #define is the proper way to do this.[/QUOTE] It can make sense to use "#pragma once" in [i]addition[/i] to the usual include guards, for a possible improvement in compile time when the compiler supports it. But the difference is likely to be negligible unless the project is large, and you should always use the #ifndef/#define to ensure portability across compilers. I'm not sure whether the #pragma ought to go before the #ifndef or after the #define, though, when both are used. It might not matter.
[QUOTE=Wyzard;36489653]for a possible improvement in compile time when the compiler supports it.[/QUOTE] Right, years ago the pragma was faster due to something about reevaluating already included files or something. Nowadays it's not an issue.
[QUOTE=Wyzard;36489653]It can make sense to use "#pragma once" in [i]addition[/i] to the usual include guards, for a possible improvement in compile time when the compiler supports it. But the difference is likely to be negligible unless the project is large, and you should always use the #ifndef/#define to ensure portability across compilers. I'm not sure whether the #pragma ought to go before the #ifndef or after the #define, though, when both are used. It might not matter.[/QUOTE] Before, otherwise what would be the point if it's already been include guarded.
Well, I [i]think[/i] the way "#pragma once" typically works is that the compiler won't even bother opening the file the second and subsequent times. If that's the case, it shouldn't matter where the #pragma line is as long as the compiler sees it when it reads the file the first time. I've seen someone claim — though I haven't researched this — that modern compilers can recognize the common pattern for include guards and treat them specially, much like "#pragma once": if the first line of the file is an #ifndef, and its #endif is on the last line, then the compiler can just ignore subsequent inclusions instead of running it through the preprocessor (and producing zero lines of output) each time. Having a #pragma before the #ifndef line could potentially interfere with the compiler recognizing the include-guard pattern and doing its special handling. But again, I haven't researched this, and it'd really only affect a compiler that [i]does[/i] treat include guards specially, but [i]doesn't[/i] understand "#pragma once".
[QUOTE=Wyzard;36496543]Well, I [i]think[/i] the way "#pragma once" typically works is that the compiler won't even bother opening the file the second and subsequent times. If that's the case, it shouldn't matter where the #pragma line is as long as the compiler sees it when it reads the file the first time. I've seen someone claim — though I haven't researched this — that modern compilers can recognize the common pattern for include guards and treat them specially, much like "#pragma once": if the first line of the file is an #ifndef, and its #endif is on the last line, then the compiler can just ignore subsequent inclusions instead of running it through the preprocessor (and producing zero lines of output) each time. Having a #pragma before the #ifndef line could potentially interfere with the compiler recognizing the include-guard pattern and doing its special handling. But again, I haven't researched this, and it'd really only affect a compiler that [i]does[/i] treat include guards specially, but [i]doesn't[/i] understand "#pragma once".[/QUOTE] But don't modern compilers just ignore # lines if it's not understood by the compiler? Like #warning which iirc gets ignored by VS. [img]http://puu.sh/DLOt[/img] Oh, I guess not. That's really dumb.
That's why I said "potentially": it depends on how a particular compiler is coded to recognize include guards. One would hope that comments and blank lines before the #ifndef are allowed, and it'd make sense for unrecognized pragmas to be allowed too, but I can't say for certain that they are.
This is the only thing I hate about C++. WAY TOO MUCH STUFF is not standard and should be. Struct packing, size of variable types like int, long, etc, pragma once, warnings. It forces you to not only concentrate on writing operating-system portable code but compiler portable too.
Some of that stuff is influenced mainly by the CPU, not the whim of the compiler vendor. Integer sizes are generally determined by the CPU's register size, and structure packing is determined by its data alignment requirements.
[QUOTE=flayne;36498546]This is the only thing I hate about C++. WAY TOO MUCH STUFF is not standard and should be. Struct packing, size of variable types like int, long, etc, pragma once, warnings. It forces you to not only concentrate on writing operating-system portable code but compiler portable too.[/QUOTE] A lot of this can be helped with good libraries or using the proper types. There's no reason why you need to know what size int or long will be.
[QUOTE=gparent;36508999]There's no reason why you need to know what size int or long will be.[/QUOTE] [cpp] int SomeNationalDebt = 15814803985123; std::cout << SomeNationalDebt; [/cpp] ...sorry, couldn't resist. Was probably meant that there is no reason why you need to know what size int or long will be [i]on the target platform[/i] - just #include <stdint.h> (which is very common) and you have all the flavors of integers you would expect. It even specifies types for optimum speed or optimum memory usage (instead of only exact size). [QUOTE=Wyzard;36489653]you should always use the #ifndef/#define to ensure portability across compilers.[/QUOTE] You've piqued my interest; what compilers do you use on a day-to-day basis that do not support #pragma once? [url=http://stackoverflow.com/questions/787533/is-pragma-once-a-safe-include-guard]I feel like this debate has probably been done before.[/url] [quote=Mircea Chirea]I simply just don't use #pragma once, as it has no benefit. To avoid clashing with other include guards I use something like: CI_APP_MODULE_FILE_H --> CI = Company Initials; APP = Application name; the rest is self-explanatory.[/quote] I simply just don't use #pragma once, as it has no benefit over repeatedly typing out long strings of boilerplate for every single header I write in response to a well-defined problem already solved automatically by all modern compilers years ago. I also protest the use of machines to process mass mail as it has no benefit over manual labor.
[QUOTE=Wyzard;36506887]Some of that stuff is influenced mainly by the CPU, not the whim of the compiler vendor. Integer sizes are generally determined by the CPU's register size, and structure packing is determined by its data alignment requirements.[/QUOTE] As regards to struct packing I meant #pragma pack and the like not being standardized. There's no one way to tell the compiler how to pack them.
[QUOTE=Night-Eagle;36510366]Was probably meant that there is no reason why you need to know what size int or long will be [I]on the target platform[/I][/QUOTE] I meant exactly what I typed. If you want to know the size of something, used fixed- or least-widthed integers like you said. If you're using int, you don't care about the size. [QUOTE=Night-Eagle;36510366]just #include <stdint.h>[/QUOTE] The correct header is <cstdint> (you never use .h for standard headers in C++). There is also <boost/cstdint.hpp> if your compiler doesn't support <cstdint>. I can't bother looking myself, so I always use the boost one since I figure it's going to be updated quicker if need be. [QUOTE=Night-Eagle;36510366]You've piqued my interest; what compilers do you use on a day-to-day basis that do not support #pragma once?[/QUOTE] None, I simply don't go out of my way to write non-standard code when it has absolutely no benefit at all. (the typing argument that is often made makes no sense, if you want to save on typing make a VS macro and BOTH ways will be quicker than before). Your sarcasm would be funny if you hadn't picked the singlehandedly most retarded example of writing a include guard ever. I just use FILENAME, and since I already need to have file name collision discipline, I never have collisions.
We're painting the fucking bikeshed red guys. There is no reason to discuss include guards whether you use the standard construct or the non-standard one which saves two lines. It's really a non-issue. Let's discuss something (slightly more) interesting that we can all agree on like how broken a textual include system is in the first place.
[QUOTE=blankthemuffin;36519678]like how broken a textual include system is in the first place.[/QUOTE] You might be interested in the [url=http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2316.pdf]modules proposal[/url].
[QUOTE=Wyzard;36524542]You might be interested in the [url=http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2316.pdf]modules proposal[/url].[/QUOTE] By the time that is included in the standard we'll probably be in 2020 or something, might as well learn D.
I've got another issue. It's not related to pointers or vectors, but I thought seeing as I already have a thread here I might as well just post it here rather than starting a new thread. I'm trying to make it so that when you hover over a square, that square gets highlighted. I've written some code to get a transparent square to appear, but I'm having trouble actually getting it to run. This is the Board.cpp code: [code] #include <SFML/Graphics.hpp> #include <SFML/Window.hpp> #include <vector> #include <iostream> #include "board.h" #include "piece.h" using namespace std; Board::Board() { } void Board::FENReader(sf::RenderWindow *win) { int i = 0; char fenInit[] = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR|"; //char fenInit[] = "2r3k1/p4p1p/2r3p1/p1bp4/b4B2/P1R1PN2/5PPP/1R2K3|"; setCoords(); //// Sets half the board to 0, the other half to -1. //board[i] = -1; //for (i = 0; i < 128; i++) //{ // board[i] = 0; // k++; // if (k == 8) // { // i += 8; // k = 0; // } //} // Numbers the board[] array from 0 to 127. for (i = 0; i < 128; i++) { board[i] = i; } int col = 0; int row = 7; i = 0; int coordPos = 0; do { switch(fenInit[i]) { case 'r': initPlacement(bRook, row * 16 + col, coordPos, win); col++; coordPos++; break; case 'n': initPlacement(bKnight, row * 16 + col, coordPos, win); col++; coordPos++; break; case 'b': initPlacement(bBishop, row * 16 + col, coordPos, win); col++; coordPos++; break; case 'q': initPlacement(bQueen, row * 16 + col, coordPos, win); col++; coordPos++; break; case 'k': initPlacement(bKing, row * 16 + col, coordPos, win); col++; coordPos++; break; case 'p': initPlacement(bPawn, row * 16 + col, coordPos, win); col++; coordPos++; break; case '/': row--; col=0; break; case '1': col+=1; coordPos+=1; break; case '2': col+=2; coordPos+=2; break; case '3': col+=3; coordPos+=3; break; case '4': col+=4; coordPos+=4; break; case '5': col+=5; coordPos+=5; break; case '6': col+=6; coordPos+=6; break; case '7': col+=7; coordPos+=7; break; case '8': col+=8; coordPos+=8; break; case 'P': initPlacement(wPawn, row * 16 + col, coordPos, win); col++; coordPos++; break; case 'R': initPlacement(wRook, row * 16 + col, coordPos, win); col++; coordPos++; break; case 'N': initPlacement(wKnight, row * 16 + col, coordPos, win); col++; coordPos++; break; case 'B': initPlacement(wBishop, row * 16 + col, coordPos, win); col++; coordPos++; break; case 'Q': initPlacement(wQueen, row * 16 + col, coordPos, win); col++; coordPos++; break; case 'K': initPlacement(wKing, row * 16 + col, coordPos, win); col++; coordPos++; break; } i++; } while (fenInit[i] != '|'); } void Board::initPlacement(Piece Piece, int sq, int coordPos, sf::RenderWindow *win) { pieceMain pieceMain; pieceMain.setPiece(Piece, coords[coordPos], win); sqSelect(win); } void Board::setCoords() { int i = 0; int k = 0; int x = 13; int y = 0; int j; Vector2D xycoords; // Creates xycoords object /* Loops through and stores coordinates in xycoords The i integer sets the number of coordinates to store (64 for 64 squares on the board) The second for loop uses the j integer to count along the x axis and store the coordinates for each column square in the current row. When j reaches the 8th column, it breaks out of the loop and goes up one row, and moves back to the left-hand square. */ for (i = 0; i<64; i++) { for (j = 0; j < 8; j++) { xycoords.x = x; xycoords.y = y; x += 100; //coords->push_back(xycoords); coords.push_back(xycoords); i++; } //y = y - 100; y += 100; x = 13; j = 0; } } void Board::sqSelect(sf::RenderWindow *win) { sf::Shape Square; Square.AddPoint(0, 0); Square.AddPoint(100, 0); Square.AddPoint(100, 100); Square.AddPoint(0, 100); Square.Move(200,600); Square.SetColor(sf::Color(255,153,0,10)); win->Draw(Square); } [/code] The last function, sqSelect() is the code that creates the transparent square. The function is currently being called in initPlacement(). For some reason, the square will only display if it is called inside the initPlacement() function. If I move it to another function, it will still call the function and run the code, but it won't display anything on the screen. This is a problem, because I'm trying to call the function inside main.cpp, which is where the game loop is, which is where I'll need to call it if I want to have the square appear over the square the mouse is hovering over.. Does anyone have any idea why the code is acting like this? I've no idea. Thanks for your help.
Here's main.cpp, where I'm trying to call the function from: [code] #include <SFML/Graphics.hpp> #include <SFML/Window.hpp> #include <iostream> #include "board.h" int main() { // Create the main rendering window sf::RenderWindow App(sf::VideoMode(800, 800, 32), "SFML Graphics"); // Load chessboard image from file sf::Image chessboard; if (!chessboard.LoadFromFile("board.tga")) return EXIT_FAILURE; // Create the sprite for the chessboard sf::Sprite chess(chessboard); chess.SetImage(chessboard); // Display chessboard sprite App.Draw(chess); Board Board; Board.FENReader(&App); //Board.sqSelect(&App); // Display window contents on screen App.Display(); // Start game loop while (App.IsOpened()) { // Process events sf::Event Event; while (App.GetEvent(Event)) { // Close window : exit if (Event.Type == sf::Event::Closed) App.Close(); // Escape key : exit if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape)) App.Close(); } } return EXIT_SUCCESS; } [/code]
Sorry, you need to Log In to post a reply to this thread.