Several C++ questions. (Pointers & 2D arrays)
59 minutes ago, fpo said:I'm guessing I forward declared incorrectly by using struct instead of class.
No, in C++ a struct and a class are the same, except for the fact that struct members and inheritance are public by default whereas they are private by default for class.
1 hour ago, fpo said:Can you call functions based on a pointer?
IEforward declare a class,
hold a pointer to a class not included in the header file
in CPP call a function part of the pointed to object's class.
I'm guessing the CPP would require an include to the header of the class that was forward declared.
Correct. As per the given example you can include the header of the forward declared class in the CPP file and then you can use it completely.
1 hour ago, fpo said:Wouldn't a function containing a "dumb" pointer have an issue if an exception was thrown? Don't you have to "delete" it to clear its use?
The dumb pointer simply refers to a object that is owned elsewhere, so it can be accessed, but the owner is responsible for it's deletion. In the given smart pointer example the memory is owned by std::unique_ptr pThing in function SomeFunction. A dumb pointer to the managed object is passed to function DoSomething so that DoSomething can access the object, but the ownership and responsibility remains with pThing in SomeFunction. If DoSomething throws then the stack will be unwound until someone tries to catch the exception. It's not being caught in DoSomething so that function will exit. It's not being caught in SomeFunction either, so that function will exit as well, but because pThing is a automatic variable in SomeFunction it will go out of scope once that function exits and it's destructor will be called, which will delete the managed memory.
1 hour ago, fpo said:In the above section, you said if "DoSomething" throws an exception, "pThing will automatically be deleted." Would this cause an error if you tried to use "pThing" after the exception is thrown?
You can't even do that. If DoSomething throws the stack will be unwound until the exception is caught. SomeFunction will exit immediately and execution will resume at some lower level where the exception is caught.
1 hour ago, fpo said:How do you make a smart pointer hold no value? IE "I am currently not pointing to anything" without completely destroying the pointer. Like how you can set a variable to "null" in some languages with the variable still existing & being able to be read, and written to.
How do you create a smart pointer without giving it a value? Or is that impossible with the RAII? I want all the "Tile" objects to point to nothing until a "Thing" tells a "Tile" that the "Tile" can point to the current "Thing" and then when a Thing leaves the Tile or is gameplay destroyed (like killing an enemy) to have Tile point to nothing.
A default constructed std::unique_ptr is empty. You can manually release it and it has a overload for operator bool to check if it's currently managing something:
std::unique_ptr<Thing> pThing; //default constructed unique_ptr contains nullptr by default if (pThing) //operator bool { //will not execute, pThing contains nullptr } pThing.reset(new Thing); //Create new Thing and have pThing manage it (don't do this, use std::make_unique) if (pThing) //operator bool { //will execute, pThing does not contain nullptr } pThing.release(); //Delete object under management, pThing free again.
HOWEVER The point of the story was that smart pointers are only to be used when you need to manage dynamically allocated memory. In your case that doesn't seem to be the case. If your array of Tiles has a size that is known at compile time, just make it a std::array (or your own Array2D that uses std::array under the hood). If the size is unknown at compile time then use std::vector (or your own Vector2D that uses std::vector under the hood).
1 hour ago, fpo said:How do you pass a normal array to a function by reference?
A C style array decays to a pointer:
void UseIntArray(int* array, int size) { for (int i = 0; i < size; ++i) { array[i] = //do something... } } int main() { int array[10]; UseIntArray(array, 10); return 0; }
1 hour ago, fpo said:How do you pass a vector or array to a function by reference? Same way as an integer variable?
C++ actually supports references as a separate concept and those are preferred:
void UseIntVector(std::vector<int>& vec) { for (auto& elem : vec) { //Use elem } } int main() { std::vector<int> vec; //populate vector... UseIntVector(vec); return 0; }
But you could use pointers if you wanted to:
void UseIntVector(std::vector<int>* pVec) { for (auto& elem : *pVec) { //Use elem } } int main() { std::vector<int> vec; //populate vector... UseIntVector(&vec); return 0; }
A std::array is somewhat trickier as it's size is part of the template. So you'd either have to write your function to only accept std::arrays of fixed size or the function itself has to be a template:
template <std::size_t size> void UseIntArray(std::array<int, size>& array) { for (auto& elem : array) { //Use elem... } } int main() { std::array<int, 100> array; UseIntArray(array); //Template deduction passes along size automatically. return 0; }
1 hour ago, fpo said:Straight Stewie recommended the possibility of a 2D array by making an array contain arrays of type.
int size = 10; int otherSize = 15; std::array<std::array<Thing, size>, otherSize>If I do this method (provided it's a good method to follow) how would I pass it to a function & how would I access specific indices in the function?
It's not recommended as it still is not guaranteed to be a continuous block of memory.
Many of your technical problems are artificial, stemming from poor overall design, so I'd focus my efforts there. For example, your "map" should probably be a class in it's own right, not a plain 2D array of Tiles. Then the "map" object manages it's implementation details internally and other objects ask the map to perform tasks. This keeps "map"'s implementation details restricted to the "map" class and stops it from being scattered all around the code as it is now.
In simple terms, The "Human" object asks a "Dog" object to walk. The "Human" object doesn't go and manipulate the dog's legs directly.
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now