I am creating an abstract geometry class that has children classes. However, I want that the class RightCircularCone also has its own private variables that define its apex coordinates, such that the abstract class is not unnecessary big in memory size for objects of type Sphere that don't need storage of apex variables.
However, I can't seem to access the functions and variables of RightCircularCone when I load them from a container that uses smart pointers, as it keeps being defined as its parent class Shape. Can anyone see what is going wrong?! Appreciate it!
/* shapes.hpp */
class Shape{
public:
unsigned int color;
float radius;
float x,y,z;
public:
void SetSpatial(float radius, float x, float y, float z);
unsigned int GetColor(void);
void SetColor(unsigned int color);
virtual bool PointInside(const std::array<double,3> &point)=0;
};
class RightCircularCone : public Shape{
private:
float Ax,Ay,Az;
public:
bool PointInside(const std::array<double,3> &point);
void SetApex(float x, float y, float z);
void PrintApex();
};
class Sphere : public Shape{
public:
bool PointInside(const std::array<double,3> &point);
};
The classes defined above are used in another .cpp file where methods of a class are defined:
#include "../../include/part.hpp" /* includes shapes.hpp in turn */
void Part::ReadPartFile(std::string partfile){
try{
std::ifstream dataFile;
dataFile.open(partfile);
//do checks, error badbits etc...
std::string word;
unsigned int counter=0;
while(!dataFile.eof()){
dataFile >> word;
if(word == "sphere"){
auto newSphere = std::make_shared<Sphere>();
// load variables into objects from file by checking each word by using setColor and setSpatial
shapeList[counter++] = newSphere;
} else if(word == "rccone"){
auto newRccone = std::make_shared<RightCircularCone>();
// load variables into objects from file by checking each word by using setColor and setSpatial and setApex
shapeList[counter++] = newRccone;
}
}
dataFile.close();
} catch(std::ifstream::failure e) {
//do exception handling here if necessary
}
Now, when I use an iterator over the map std::map<unsigned int, std::shared_ptr<Shape> > shapeList; as defined in part.cpp I can never access the methods of children classes Sphere and RightCircularCone as the map returns a type of Shape, even though I used a smart pointer!!!
Anybody knows why and a potential fix (or neater way to set up the classes)??
Thanks!
//EDIT:
This is the error I get:
error: no member named 'PrintApex' in 'Shape'
iterator->second->PrintApex();
Think about it. You create a vector of shared_ptr of Shape. As far as the vector is concerned you are storing Shape instances in it, not Sphere or whatever.
Now, you happen to initialize your Shape instance with a Sphere and you store the ptr of that Sphere into the vector. Next item is a RightCircularCone, again stored as a Shape.
You access the first element, and as far as the compiler is concerned at THAT point, you only have a Shape. It cannot deduce the actual type as this happens at runtime. So, as far as the compiler is concerned you have a Shape instance with whatever the Shape class contains.
Now, you need to somehow inform the compiler about the type you want to work with, so it can find the methods you want to access. For that, you use dynamic_cast to specify the intent that this is a Sphere and you should have access to Sphere members.
More details about dynamic_cast, here http://en.cppreference.com/w/cpp/language/dynamic_cast
Edit. A note about design.
In principle, you want to offload as much to the compiler. If there is something that compiler can do, let him do it. So, if you want to do something different for each subclass of Shape, instead of checking a string literal for the Shape type you could use virtual specialized functions that act on a specific type. E.g.
virtual void printMe(Sphere & sphere) {
cout << "This is a sphere with radious x" << endl;
}
virtual void printMe(RightCircularCone & cone) {
cout << "This is a cone" << endl;
}
//and you use like
for (auto & shape: shapes) { printMe(shape); }
//and the correct functions are resolved automagically
it may seem a bit more work, but in the long run it is actually simpler as you offload the picking of the functionality to someone else.
Related
I have a 2d physics engine that I've been programming in C++ using SFML; I've implemented a rough collision detection system for all SandboxObjects (the base class for every type of physics object), but I have a dilemma.
I plan to have many different derived classes of SandboxObjects, such as Circles, Rects, and so on, but I want a way to check if the roughHitbox of each SandboxObject collides with another.
When the program starts, it allocates memory for, let's say, 10,000 Circles
int circleCount = 0;//the number of active Circles
constexpr int m_maxNumberOfCircles = 10000;//the greatest number of circles able to be set active
Circle* m_circles = new Circle[m_maxNumberOfCircles];//create an array of circles that aren't active by default
like so.
and every time the user 'spawns' a new Circle, the code runs
(m_circles + circleCount)->setActive();`
circleCount++
Circles that aren't alive essentially do not exist at all; they might have positions and radii, but that info will never be used if that Circle is not active.
Given all this, what I want to do is to loop over all the different arrays of derived classes of SandboxObject because SandboxObject is the base class which implements the rough hitbox stuff, but because there will be many different derived classes, I don't know the best way to go about it.
One approach I did try (with little success) was to have a pointer to a SandboxObject
SandboxObject* m_primaryObjectPointer = nullptr;
this pointer would be null unless there were > 1 SandboxObjects active; with it, I tried using increment and decrement functions that checked if it could point to the next SandboxObject, but I couldn't get that to work properly because a base class pointer to a derived class acts funky. :/
I'm not looking for exact code implementations, just a proven method for working with the base class of many different derived classes.
Let me know if there's anything I should edit in this question or if there's any more info I could provide.
Your problems are caused by your desire to use a polymorphic approach on non-polymorphic containers.
The advantage of a SandboxObject* m_primaryObjectPointer is that it allows you to treat your objects polymorphicaly: m_primaryObjectPointer -> roughtHitBox() will work regardless of the object's real type being Circle, Rectangle, or a Decagon.
But iterating using m_primaryObjectPointer++ will not work as you expect: this iteration assumes that you iterate over contiguous objects in an array of SandboxObject elements (i.e. the compiler will use the base type's memory layout to compute the next address).
Instead, you may consider iterating over a vector (or an array if you really want to deal with extra memory management hassle) of pointers.
vector<SandboxObject*> universe;
populate(universe);
for (auto object:unviverse) {
if (object->isActive()) {
auto hb = object -> roughtHitBox();
// do something with that hitbox
}
}
Now managing the objects in the universe can be painful as well. You may therefore consider using smart pointers instead:
vector<shared_ptr<SandboxObject>> universe;
(little demo)
It's hard to answer this without knowing the requirements but you could have sandbox maintain two vectors of active and inactive objects, and use unique_ptrs of the base class for memory management.
Some code below:
#include <vector>
#include <memory>
#include <iostream>
class sandbox_object {
public:
virtual void do_something() = 0;
};
class circle : public sandbox_object {
private:
float x_, y_, radius_;
public:
circle(float x, float y, float r) :
x_(x), y_(y), radius_(r)
{}
void do_something() override {
std::cout << "i'm a circle.\n";
}
};
class triangle : public sandbox_object {
private:
float x1_, y1_, x2_, y2_, x3_, y3_;
public:
triangle( float x1, float y1, float x2, float y2, float x3, float y3) :
x1_(x1), y1_(y1), x2_(x2), y2_(y2), x3_(x3), y3_(y3)
{}
void do_something() override {
std::cout << "i'm a triangle.\n";
}
};
class sandbox {
using sandbox_iterator = std::vector<std::unique_ptr<sandbox_object>>::iterator;
private:
std::vector<std::unique_ptr<sandbox_object>> active_objects_;
std::vector<std::unique_ptr<sandbox_object>> inactive_objects_;
public:
void insert_circle(float x, float y, float r) {
active_objects_.push_back( std::make_unique<circle>(x, y, r) );
}
void insert_triangle(float x1, float y1, float x2, float y2, float x3, float y3) {
active_objects_.push_back( std::make_unique<triangle>(x1,y1,x2,y2,x3,y3));
}
sandbox_iterator active_objs_begin() {
return active_objects_.begin();
}
sandbox_iterator active_objs_end() {
return active_objects_.end();
}
void make_inactive(sandbox_iterator iter) {
std::unique_ptr<sandbox_object> obj = std::move(*iter);
active_objects_.erase(iter);
inactive_objects_.push_back(std::move(obj));
}
};
int main() {
sandbox sb;
sb.insert_circle(10.0f, 10.0f, 2.0f);
sb.insert_triangle(1.0f, 1.0f, 2.0f, 2.0f, 2.0f, 1.0f);
sb.insert_circle(1.0f, 6.0f, 4.0f);
sb.make_inactive(sb.active_objs_begin());
(*sb.active_objs_begin())->do_something(); // this should be the triangle...
return 0;
}
I'm learning C++.
Came across data encapsulation and data hiding at a website, check out the following piece of code:
#include<iostream.h>
#include<conio.h>
class sum {
private: int a, b, c;
public:
void add() {
clrscr();
cout << "Enter any two numbers: ";
cin >> a >> b;
c = a + b;
cout << "Sum: " << c;
}
};
void main() {
sum s;
s.add();
getch();
}
NOW. As it says here that:
The main advantage of using of encapsulation is to secure the data from other methods, when we make a data private then these data only use within the class, but these data not accessible outside the class.
What happens underneath the code, what does the compiler do that makes it inaccessible to other classes? And in the given example what was the reason behind defining a,b and c as private.
What were they trying to achieve by hiding "just the declarations of the three variables"? Because anyone can see that inside public three numbers being used are a,b, and c - first two for input and third one for output.
How is this possible that the data under private can't be accessed
outside the class?
Compiler makes sure you don't. If you try to access say a outside class, your code will not compile.
And in the given example what was the reason behind defining a,b and c
as private.
It could be anything! But as a result, a,b and c are not accessible outside members of class.
Basically you want to hide some variables in your class for the sake of consistency. So that you or your clients can not produce a code that makes unwanted and uncontrolled changes.
Updates:
What happens underneath the code, what does the compiler do that makes
it unaccessible to other classes?
Compiler implementation check for access level while producing code. If there is something wrong, you will get a syntax error and no machine code will be generated from your file.
And in the given example what was the reason behind defining a,b and c
as private; what were they trying to achieve by hiding "just the
declarations of the three variables"? Because anyone can see that
inside public three numbers being used are a,b, and c - first two for
input and third one for output.
You don't hide variables in your class to make them invisible to others. Private variables that are not intended to be used from outside of the class can be marked as private to limit the potential for coding errors.
As an example consider following class:
class rectangle {
public:
int width;
int height;
int area;
};
void something_important(const rectangle& r) {
// ...
}
What happens if I pass a rectangle of width -10, height 0 and area of -15? There could be a plane crash or a nuclear weapon launched to some wrong target... So I will make sure my rectangles are always valid:
class rectangle {
public:
void set_width(int w) {
if(w) width = w;
else width = 0;
area = width*height;
}
int get_width() const {return width;}
void set_height(int h) {
if(w) height = h;
else height = 0;
area = width*height;
}
int get_height() const {return height;}
int get_area() const {return area;}
private:
int width;
int height;
int area;
};
So no one can make a rectangle of negative height or width, and no one can make a rectangle having a wrong area. (you can not actually change area directly)
I hope it makes sense for you now.
What happens underneath the code, what does the compiler do that makes it unaccessible to other classes?
Not much. The compiler doesn't protect against access to the data. It protects against access to the name of the data. For instance:
void foo(class bar&, int&);
class bar {
int i = 0;
public:
void baz() {
foo(*this, i);
}
};
void foo(class bar& b, int& i) {
//b.i = 42; // This is an error. b.i is private
i = 42; // This is okay, no matter what the local i refers to
}
In the example above, foo() cannot access b.i by name, because it's a private data member. But it can still modify it if it obtains a reference by other means. The member function baz() which has access to that name, binds it to the reference that foo() accepts. Thus allowing for its modification from outside the class's scope.
i trying to implement the following link http://in.mathworks.com/help/vision/examples/motion-based-multiple-object-tracking.html in opencv and c++.
I have created a class say ex:
class assign
{
vector <int> id;
vector <int> area;
vector<Point> centroid;
};
After this i have created an object
assign id;
Now i want to assign the centroid value and other values too. what i tried is
id.centroid (p);
where p is a "point" But i'm getting error for this. I don't know where i'm going wrong.
centroid is a private member of class assign. If you want to access it directly, you should make it public
class assign
{
public:
vector<Point> centroid;
//...
};
And if you want to add a Point into centroid, you should
id.centroid.push_back(p);
The main answer is already given by songyuanyao. What I want to add is a possible solution which allows you to use the member variables like you already tried it.
If you want to get and set the member centroid with id.centroid(p) you could go with the following class declaration:
class Assign
{
public:
vector<Point> centroid();
void centroid(vector<Point> c);
private:
vector<Point> m_centroid;
};
The definition might then look like this:
// getter
vector<Point> Assign::centroid() {
return m_centroid;
}
// setter
void Assign::centroid(vector<Point> c) {
m_centroid = c;
}
Now if you use id.centroid(p) to set the member the overloaded setter will be called and will set the variable. If you call p = id.centroid() (empty parameter list) the overloaded getter will be called and will return the current m_centroid.
To add to the previous answers; if you want to expand on your class this can be done for you during construction of your object.
class Assign {
private:
std::vector<int> m_vIds;
std::vector<int> m_vAreas;
std::vector<Vec2> m_vCentroids;
public:
Assign(); // Default Constructor Same As What You Have But Not Declared.
Assign( int* pIds, int* pAreas, int* pCentroids ); // Create By Using Pointers
// Create By Passing In Either Pre Filled Vectors Or Even An Empty
// Vectors To Be Filled Out Later. Passes By Reference. This Will
// Also Set The Variables That Are Passed In From The Caller.
Assign( std::vector<int>& vIds, std::vector<int>& vAreas, std::vector<Vec2>& vCentroids );
// Since You Are Using Vectors Within This Class It Is Also Good To
// Have A Destructor To Clear These Out Once The Object Is Done And
// Ready To Be Destroyed Or Removed From Memory
~Assign();
};
// The Destructor Would Look Like This
Assign::~Asign() {
if ( !m_vIds.empty() ) {
m_vIds.clear();
}
if ( !m_vAreas.empty() ) {
m_vAreas.clear();
}
if ( !m_vCentroids.empty() ) {
m_vCentroids.empty();
}
} // ~Assign
// NOTE: I used Vec2 instead of point due to my use of programming
// 2D & 3D Graphics Rendering Engines; Most Graphics APIs and Libraries
// along with Most Math Libraries Will Not Have A Point Class; Most Will
// Use Vec2 or Vec3 - Vector2 or Vector3 & Vector4 Since in terms of
// memory they are exactly the same thing. It is up to you to know which
// objects are points or locations, and which are vectors as in forces,
// velocities, accelerations, directions, normals etc. The only major
// difference between a discrete Point Class or Structure versus a Vector
// Class is that the Vector Class usually has operations defined with it
// to do vector mathematics such as addition, subtraction, multiplication by
// value, multiplication by vector, division by value, division by vector,
// cross & dot product, comparisons, testing if vector is 0, setting it to
// be a normal vector, returning the magnitude or length and a few others.
// The general point class or object is usually just data values or
// simply coordinates without operations.
I'm currently pondering how should I go about making a 2D vector array for a sort of a game board.
The board should be vectors because the size can vary, and each "square" should contain information about what objects are in that square.
The problem is that there can be overlapping objects, and the objects may not be the same type or class.
This is what I'm currently considering: (pseudo code)
struct Square {
vector<enum type>;
vector<pointers to objects>;
};
vector< vector <Square> >;
And the pointer's would point to different vector arrays each holding specific objects.
I'm unsure how to make such functionality or if this is even possible, and I'm seriously thinking this might be more complicated then it needs to be..
Some objects must be classes, but I could make all the types of objects in the game board classes that inherit from one master class.. But in the end the objects are completely different so I'm not sure if that makes much of a difference.
Am I just being blind and missing a easier way to do what I'm trying to do: 2D array holding different types of elements that can also overlap in the array?
I'd really appreciate any help, snippets or insight.
Notes:
Board size won't chance after creation.
Objects must be able to move around in the board.
Here's what I would suggest.
#include <boost/shared_ptr.hpp>
class GameObject {
public:
virtual ~GameObject() {}
enum Type {
FOO,
BAR
};
virtual Type type() const = 0;
virtual std::string name() const = 0;
virtual void damaged() {}
};
class FooObject : public GameObject {
public:
Type type() const { return FOO; }
std::string name() const { return "Foo object"; }
void damaged() {
std::cout << "Foo was damaged!" << std::endl;
}
};
class BarObject : public GameObject {
public:
Type type() const { return BAR; }
std::string name() const { return "Bar object"; }
// Bar object doesn't respond to damage: no need to override damaged()
};
class Square {
std::vector<boost::shared_ptr<GameObject> > objects;
};
class Board {
// Details of the implementation here not important, but there
// should be a class to hide them.
Square* squares;
int width, height;
Board(int width, int height) :
squares ( new Square[ width * height ] ),
width ( width ),
height ( height )
{
}
~Board() {
delete [] squares;
}
Square& square(int x, int y) {
if( x < 0 || x >= width || y < 0 || y >= height ) {
throw std::logic_error( "accessed square out of bounds" );
}
return squares[ x + width * y ];
}
};
Summary:
Have a single base class for all sorts of objects that can be placed on a game board.
A class of this type must have a virtual destructor, even if it's trivial. This is because you will be deleting things through GameObject pointers.
If it's necessary to distinguish the game objects, use a virtual method returning a 'type' value.
As far as it's not necessary to use it, don't use that type value, but use other virtual methods that do meaningful things instead. Using the type value (and then generally casting to the subtype) should be considered a last resort. For instance (inventing details about your game freely):
Every object has a name that shows when you put the cursor over it. This is returned in name().
Events in the game may cause 'damage' an object. This only applies to some sorts of objects, so the default action on damaged() is to do nothing. Foo-objects, which respond to damage, override this with an actual action.
However you implement the board, hide your exact implementation away in a class. (Don't take my code as an indication that you shouldn't use vector<> for this, that's definitely fine. I have a slight personal preference against vector< vector<> > here, but that's not too bad either.)
Use shared pointers for the game objects.
Boost has a great and widely used implementation.
If you can't use shared pointers, control the lifetime of your game objects outside the Square class (say, in a master list of all game objects in the Board class), and then use raw pointers in the Square class.
If you do use shared pointers, and it's the first time you do, briefly read up on them first. They're not magic, you need to beware of certain things such as circular references.
Depending on your needs, you may want to have a "backlink" in GameObject to the squares, or the coordinates of the squares, that contain pointers to that GameObject. This will allow you to easily remove objects from the board and move them around.
I am implementing a simple board game (Breakthrough) using OpenGL (plus GLUT and GLUI).
I'm thinking of implementing a Board class, which will have a vector<vector<Cell> > as one of its attributes. Cell represents a space in the game board. It can contain a GameObject. GameObject will be a pure abstract class. It mandates that its derivative classes implement render(), for example. Possible derivative classes will be:
Blank, representing an empty space
Pawn, representing a pawn (the only possible pieces in Breakthrough)
The board will be rendered by first rendering the board, then iterating through each Cell, getting its contents and calling render() for each of them.
The only possible way I can think of to achieving this is making the GameObject in Cell a pointer (board[y][x].getContents()->render(), where getContents() returns the GameObject*)
Is this the best way to do this? Is this an appropriate usage of pointers?
Let me promote my comment into an answer. This doesn't mean that it's in any sense complete, only that this allows me to spell out some code examples. My original comment:
That's OK, though you probably would do better with a std::unique_ptr<GameObject> or a std::shared_ptr<GameObject> so you don't get lost amids the manual lifetime management issues. Finally, how about a flat 1-D array accessible in strides?
Here's how I might go about this:
#include <vector>
#include <memory>
struct GameObject { virtual void render() const = 0; virtual ~GameObject() { } };
class Cell
{
std::unique_ptr<GameObject> m_go;
public:
void render() const { m_go->render(); }
Cell() : m_go(new BlankCell) { }
// more functions to reassign the cell value etc.
};
class Board
{
std::vector<Cell> m_board;
std::size_t m_length;
public:
Board(std::size_t length) : m_board(length * length), m_length(length) { }
Cell & cell(std::size_t i, std::size_t j) { return m_board(j + i * m_length); }
Cell const & cell(std::size_t i, std::size_t j) const { return const_cast<Board*>(this)->cell(i, j); }
// more...
}
Yes.
Also, maybe you should use another container for your cells (some kind of matrices or so)