Recursive function pointers. Stroustrup's example - c++

Currently I'm reading Stroustrup Programming: Principles and Practice C++. I faced up with this example:
typedef void (*Pfct0)(struct Shape2*);
typedef void (*Pfct1int)(struct Shape2*,int);
struct Shape2{
Pfct0 draw;
Pfct1int rotate;
};
void draw(struct Shape2* p)
{
(p->draw)(p);
}
void rotate(struct Shape2* p,int d)
{
(p->rotate)(p,d);
}
int f(struct Shape2* pp)
{
draw(pp);
return 0;
}
I cannot get what functions draw and rotate actually do.
I know what is typedef, function pointer, -> operator.
As I understand p->draw function will call itself recursively. Am I right?
What practical uses of making such functions as draw or rotate?

It appears to me that Stroustrup is implementing object-like dispatch in pure C. Each Shape2 object has its own draw and rotate methods. Given an arbitrary Shape2 p, draw(p) looks up that p's draw method, and applies it to itself (presumably p would have some other content that draw would read and take action upon.) The function does not call itself recursively unless the particular draw function for p calls draw recursively. This is very much like what p.draw() would do in C++ if Shape2 were a base class.

Functions draw and rotate calls a functions pointed to by members of structure p, and call these functions on a pointer to this structure p.
maybe this will help:
typedef void (*pointer_to_function)(struct Shape2*);
struct Shape2{
pointer_to_function draw;
Pfct1int rotate;
};
void function(struct Shape2* p)
{
(p->draw)(p);
^^^^^^^^^
// this is pointer_to_function so call the function pointed to by it
// with some argument of type struct Shape2*, in example p itself, why not
}
The misleading in this snippet is that we don't see how pointers in objects Shape2 are initialized, but they must be initialized to point to some functions with appropriate signatures before they are passed to global draw and rotate.

Each instance of Shape2 can have its own draw and rotate functions.
If s is a pointer to a Shape,
draw(s);
is the same as
(s->draw)(s);
This could be used to implement something like
drawrect(Shape* s);
drawcircle(Shape* s);
...
Shape shapes[2];
shapes[0].draw = &drawrect;
shapes[1].draw = &drawcircle;
...
for(int i = 0; i < 2; i++) {
draw(&shapes[i]);
}

Related

Best practices working with pointers in C++ functions with structs

I'm starting with C++ programming and I believe I have got a grasp about pointers. However I'm trying to understand the best practices for pointers and functions while using struts.
Toy example code
I have made below Toy example code to exemplify two ways to perform same thing:
#include <stdio.h>
struct rectangle {
int width;
int length;
};
void printRect(rectangle rect) {
printf("Rectangle: width=%d, length=%d\n",rect.width, rect.length);
}
void doubleSizeRectangle_1(rectangle *rect) {
rect->width = rect->width*2;
rect->length = rect->length*2;
}
rectangle doubleSizeRectangle_2(rectangle rect) {
rectangle *r = &rect;
r->width = r->width*2;
r->length = r->length*2;
return *r;
}
rectangle doubleSizeRectangle_3(rectangle rect) {
rect.width = rect.width*2;
rect.length = rect.length*2;
return rect;
}
int main()
{
rectangle rect;
rect.width = 2;
rect.length = 5;
rectangle *rect_pointer = new rectangle;
rect_pointer = &rect;
printRect(rect);
printRect(*rect_pointer);
printf("Applying functions:\n");
doubleSizeRectangle_1(rect_pointer);
printRect(rect);
rect = doubleSizeRectangle_2(*rect_pointer);
printRect(rect);
rect = doubleSizeRectangle_3(*rect_pointer);
printRect(rect);
}
That code returns following output:
Rectangle: width=2, length=5
Rectangle: width=2, length=5
Applying functions:
Rectangle: width=4, length=10
Rectangle: width=8, length=20
Rectangle: width=16, length=40
The first two prints are just to check about pointers usage.
The remaining prints are to check the three functions doubleSizeRectangle_1, doubleSizeRectangle_2 and doubleSizeRectangle_3 that perform same actions in different ways. The first one returns void and uses a pointer as input, whereas the second and third one have a variable as input and return a rectangle struct. Third option seems better than second, but would like to confirm. I'm not sure about the first one compared to the rest.
Question
Which option would be better in terms of best practice and why? Is there any of these options better in terms of avoiding memory leaks? May there be any other ways using pointers, and would those be even better than those I posted?
"best" is rather subjective, but using something complicated when there is no need to is not "best" in any sense.
Don't use new. Don't use pointers when there is no need to. Prefer references over pointers when nullptr is not a valid paramter (it isn't in your case). Use const references to avoid copies:
#include <stdio.h>
struct rectangle {
int width;
int lenght;
};
void printRect(const rectangle& rect) {
printf("Rectangle: width=%d, lenght=%d\n",rect.width, rect.lenght);
}
void doubleSizeRectangle_3(rectangle& rect) {
rect.width = rect.width*2;
rect.lenght = rect.lenght*2;
}
int main()
{
rectangle rect;
rect.width = 2;
rect.lenght = 5;
doubleSizeRectangle_3(rect);
printRect(rect);
}
Your function passed a pointer and returned the modified parameter. You do not need both. I changed it to return nothing and take the paramter by reference, because passing a nullptr does not make sense here.
You should also use a constructor to initialize the structs members, and prefer the type safe C++-IO (std::cout) over the non-typesafe C-IO.
For further reading: Why should C++ programmers minimize use of 'new'?
I suggest you to avoid doing like this:
rectangle doubleSizeRectangle_2(rectangle rect) {
rectangle *r = &rect;
r->width = r->width*2;
r->lenght = r->lenght*2;
return *r;
}
you don't need to access that parameter using a pointer inside the method, you could simply access to object, because it's a copy.
As best practice, in order to minimize the risk of memory leak, the suggestion is to use smart pointers like this:
std::unique_ptr<rectangle> smartptrToRectangle(std::make_unique<rectangle>());
a smart pointer is a class that implements the RAII idiom:
RAII explanation
a smart pointer does destroy the element for you as soon as it go out of scope.
I would not use pointers for a function that edits a rectangle struct at all:
void doubleSizeRectangle(rectangle& rect)
{
rect.width = rect.width*2;
rect.lenght = rect.lenght*2;
}
The main difference between passing a pointer and a reference is just that a pointer can be unassigned while a reference always references a rectangle struct.
Your doubleSizeRectangle_1 essentially does the same thing. You should consider checking if the pointer is assigned if you want to stick to using pointers.
doubleSizeRectangle_2 makes no sense. You are passing your struct by value which means your function receives a copy of it. You then create a pointer to this object, manipulate it through that pointer to return it as a value again. The use of the pointer is useless there.
doubleSizeRectangle_3 is just doubleSizeRectangle_2 without the weird pointer. I wouldn't use this, it does at least one copy (when passing to the function) and one move operation (returning the struct from the function) that isn't nessecary for a function that just want's to edit the struct. Stick to my suggestion or your doubleSizeRectangle_1.

Assign a point to the class member

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.

Inheriting from std:: vector

I am currently creating a class that has to be derived from std:: vector. I realize its probably bad to do this but I'm required to. Now my question is how do you access the created vector in the member functions to basically make the class access itself like a regular vector of integers? For example I am looking for the equivalent of myVector.at(0) to return the first term in the vector. Also, the size of the vector should always be 6. Here is the code I have so far:
class aHistogram : public vector<int>
{
public:
aHistogram(); //default constructor for histogram class
void update(int face); //Function to update histogram
void display(int maxLengthOfLine); //Displays histogram to the scale of maxLengthOfLine using x's
void clear();//Function to clear histogram bin counts
int count(int face) const; // Function to return number of times a face has appeared
private:
int numx, m, j; //Variables used in functions
};
#endif
The function that requires the class to access itself is below, I know there is no vector called "myVector" but what I'm lost about is the equivalent syntax to be able to perform the operation.
void aHistogram::clear()
{
//Clears bin counts to 0
myVector.at(0) = 0;
myVector.at(1) = 0;
myVector.at(2) = 0;
myVector.at(3) = 0;
myVector.at(4) = 0;
myVector.at(5) = 0;
}
If the function in question isn't overridden in the derived class, you
can just call it:
void HistoGram::clear()
{
at( 0 ) = 0;
// ...
}
This is also true for operators, but you'll have to use (*this) as the
left hand operator:
void HistoGram::clear()
{
(*this)[0] = 0;
// ...
}
If the function or operator is overridden, you'll either have to
qualify the function name,
void HistoGram::clear()
{
std::vector<int>::at( 0 ) = 0;
// ...
}
or cast the this pointer to the base class type:
void HistoGram::clear()
{
(*static_cast<std::vector<int>*>( this ))[0] = 0;
// ...
}
But are you sure that you want public inheritance here? You state that
the size of the vector should always be 6. There's no way you can
guarantee that using public inheritance; at the least, you need private
inheritance, and then using declarations for the operations that you
want to support. (I've a couple of cases where I've needed restricted
std::vector like this, which I've implemented using private
inheritance. And sometimes forwarding functions, when for example
I've wanted to expose only the const version of the function.)
Also: there are very, very few cases where std::vector<>::at is
appropriate. Are you sure you don't want [], with the bounds checking
you get in most modern implementations.
Instead of deriving from std::vector, in this case contain one (as a data member).
The problem with deriving is that it's then possible to treat a Histogram instance as just a std::vector, doing things that invalidate assumptions about the values of added data members.
In more technical jargon, with class derivation you have no guaranteed class invariant above the one provided by std::vector.
As a general rule of thumb, think of data member before class inheritance.
Sometimes inheritance is the thing, even inheritance from standard library container classes (e.g., std::stack is designed for inheritance), but not in this case.
About this: the size of the vector should always be 6.
You probably want to forbid some functionality to the user of the class. For example
vector::push_back
vector::pop_back
vector::insert
are functionalities that can change the size of the vector.
You can achive this by making such functions private members in the child class:
class aHistogram : public vector<int>
{
public:
aHistogram(){};
private:
vector<int>::push_back;
vector<int>::pop_back;
vector<int>::insert;
int numx, m, j;
};

C++ STD Vector push_back doesn't seem to work

I'm making a game with SDL that used libconfig to read some settings from a file. The problem is that I made a class called ClipList that contains a std::vector<SDL_Rect> to store the settings but when trying to add SDL_Rect objects to the vector, for some reason push_back does nothing and I end up with an empty vector.
This is the class:
class ClipList
{
public:
ClipList();
ClipList(int);
virtual ~ClipList();
void addClip(int,int,int,int);
void getClip(int,SDL_Rect*);
int getLength();
protected:
private:
std::vector<SDL_Rect> clips;
};
ClipList::ClipList(int l)
{
clips.reserve(l);
}
void ClipList::addClip(int x,int y,int w,int h){
SDL_Rect rect;
rect.x = x;
rect.y = y;
rect.w = w;
rect.h = h;
clips.push_back(rect);
}
void ClipList::getClip(int i,SDL_Rect* rect){
rect = &(clips.at(i));
}
int ClipList::getLength(){
return clips.size();
}
And this is the function where I initialize the ClipList object. This function gets called from main.
void set_clips(Config* placlips,ClipList* clips, ClipList* flipclips){
const Setting& root = placlips->getRoot();
int x,y,w,h;
try{
Setting& clipsett = root["clips"];
int cliplen = clipsett.getLength();
clips = new ClipList(cliplen);
flipclips = new ClipList(cliplen);
for(int i=0;i<cliplen;i++){
const Setting& c = clipsett[i];
if(!(c.lookupValue("x",x)&&c.lookupValue("y",y)&&c.lookupValue("w",w)&&c.lookupValue("h",h))){
continue;
}
clips->addClip(x,y,w,h);
}
}catch(const SettingNotFoundException &nfex){
cerr << "Setting not found at" << nfex.getPath() << endl;
}
}
Regardless of whether the ClipList objects get initialized in main or set_clips, clips.push_back(rect) doesn't work. The capacity of the vector changes but no object gets stored so I end up with a segfault if I try to do anything else with the vector, even checking if the vector is empty or not.
I am going to guess, the signature of the function
void set_clips(Config* placlips,ClipList* clips, ClipList* flipclips);
is the culprit. You are allocating memory for clips and flipclips in this function but since the pointers are passed by value, the calling function does not see the allocated memory.
If you change the function signature to:
void set_clips(Config* placlips, ClipList*& clips, ClipList*& flipclips);
your problems should go away.
clips.push_back(rect) is working fine. Your set_clips function allocates new ClipList instances but does not pass those pointers back to the caller. The caller is probably attempting to use a garbage pointer as an initialise instance and that is why you are getting a segfault.
You need to pass the created objects back. You should use something like std::shared_ptr<> to do that instead of bare pointers.
Update on how to do this without using std::shared_ptr<>:
You need to keep track of ownership and deal with exceptions. In terms of the actual passing, the rule I use (originally from Lakos in "Large Scale C++ Software Design") is that parameters that are return values (as you are attempting to use them) are pointers, and read-only parameters are by value or const-reference. Return values come first.
So, your set_clips function should look like this:
void set_clips(ClipList** clips, ClipList** flip_clips, Config const& placlips)
When you call set_clips you pass a pointer to each pointer that will receive the allocated value, and pass a const-reference to the placlips object that is not modified by the function.
You would all it something like this:
ClipList* clips = 0;
ClipList* flip_clips = 0;
set_clips(&clips, &flip_flips, placlips);
// ... then do whatever comes next.
But combining those rules with std::shared_ptr<> or boost::shared_ptr<> is better and the "modern C++" style.

Polymorphism - Appropriate usage of a pointer to a pure abstract class?

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)