This is the code I'm trying to run:
class poly {
public:
int vnum;
vrtx vrts[this->vnum];
};
(Note: The class name "poly" and other class "vrtx" are named as such to approximate the purpose of the problematic snippet. Vrtx is a class with int x, y, z;)
At first, the code didn't contain the "this->" pointer at all. I was confused why it wasn't working, and then realized that "vnum" doesn't mean anything. I needed an object.poly.vnum sort of thing so that I'm referencing a specific value. I tried "this.," "this.poly.," and the displayed "this->," but none of them work. I'm not great with pointers, so any advice would be appreciated!
I've looked at similar questions, but none of them address this issue in such a way that I could make the necessary fix with the information provided.
Here's a code fragment that should help.
class Poly
{
public:
int vnum;
std::vector<vrtx> vrts;
Poly(int capacity)
: vnum(capacity)
{ vrts.resize(vnum);}
};
The above fragment uses std::vector since the std::vector can expand dynamically (at run-time). The constructor uses the resize method to expand the std::vector to the given capacity.
Arrays are a pain to resize during run-time, so use std::vector.
I'm new to C++ and trying to figure this out. When I compile, I get the error a nonstatic member reference must be relative to a specific object. What's the correct way of writing the code? This is what I have where numShapes is giving me the error.
class Application
private:
int numShapes;
public:
Shapes * shapes[numShapes];
I then have this in another header as my virtual base class, if that's the correct term.
class Shapes
{
virtual void draw(char letter);
virtual ~Shapes() {}
};
The code Shapes * shapes[numShapes]; is requesting the compiler to reserve numShapes amount of space. The problem is that it does not have a known value at compile time. So either make numshapes a constant, or look into dynamic memory allocation.
Instead of
Shapes * shapes[numShapes];
I suggest the use of:
std::vector<Shapes*> shapes;
Remove numShapes altogether since you can get the size from shapes.
Initialize shapes in the constructor. Something along the lines of the following should work.
Application::Application(std::size_t numShapes) : shapes(numShapes, nullptr) {}
I am trying to have a declaration of 2d array in private part of my class and then latter on, the functions of this class will use and modify the values in the array, but I am getting an error which says "I-value specified const object". What is wrong with this code and how can I fix it?
Here is a simple code demonstrating my problem
in someClass.h________________
class someClass
{
public:
//Some code here
private:
char grid[20][20];
//Some code here
}
in someClass.cpp______________
lets say one of the functions is trying to reassign the value of item in position (0,0) like so.
grid[0][0]='*';
This gives me an error saying, expression must be modifiable lvalue.
Move it from private to public so you can access it outside the class. If it is private then only functions inside the class can use it.
I have a question regarding good design in C++. I have a class A, and all objects of this class use an integer array of constant values (they should share the same array, as their values are constant). The array needs to be computed (just once) before any object A.
I thought about having another class B which contains the integer array as a static member, an init() method which would fill this array according to some formula and a static boolean flag initialized (if this variable if true then the init() method would do nothing), but I'm not sure this is the best way to solve my design issue.
So my question is, what would be a good design/way to accomplish this ?
Thanks in advance.
Since the array is constant, use const.
Since the array is shared among all instances of the class, use static.
In your header file, declare it:
class A
{
static const int the_array[10];
}
In A's source file, initialize the one instance:
const int A::the_array[10] = { ... };
Edit from comment...
Or, if the array is better generated algorithmically, use a constant pointer. The usage syntax for the array would be the same.
Note that both the array and the pointer are const.
Header:
class A
{
static const int * const the_array;
}
Source file:
namespace
{
const int * generate_my_array()
{
// Allocate an array, initialize it, return it.
}
}
const int * const A::the_array = generate_my_array();
EDIT: This question came up and I think I aced it! Go StackOverflow!! :D
I have exams coming up, and one of the questions on last year's exams was to spot the problem with implementation of the following constructor and to write a corrected one.
Rectangle::Rectangle(string col, int len, int br)
{
setColour(col);
length =len;
breadth=br;
}
The class definitions are as follows:
class Polygon
{
public:
Polygon(string col="red");
void printDetails(); // prints colour only
virtual double getArea()=0;
void setColour(string col);
private:
string colour;
};
class Rectangle : public Polygon
{
public:
Rectangle(string, int, int);
void printDetails(); // prints colour and area
// for part 3, delete the line below
double getArea();
private:
int length;
int breadth;
};
I've written the code into the compiler and it runs fine. I'm guessing the question is relating to inheritance, since string colour; is private, but setColour is public so I cant figure it out. Unless its Rectangle::Rectangle(string col, int len, int br):length(len), breadth(br) and then set the colour inside the construcor or something.
Its only worth 3 marks so its not that big a deal if nobody wants to answer, but I figure if I'm going to have a career as a programmer, its in my interest to know as much as possible. ;)
Thanks for any help.
PS, see getArea() in Rectangle. When I remove that it tells me it "cannot instantiate the abstract class". What does that mean?
EDIT: Here's the main:
void main (void)
{
Rectangle rect1 ("blue",5,6);
Rectangle *prect2 = new Rectangle("red",5,6);
rect1.setColour("red");
rect1.printDetails();
prect2->printDetails();
}
I don't see anything wrong, though you could make it more efficient by using an initialization list (otherwise your private members of both classes get initialized twice):
Rectangle::Rectangle(string col, int len, int br)
: Polygon(col), length(len), breadth(br)
{
}
Notice that the initialization list can call the constructor of Polygon as well.
See Why should I prefer to use member initialization list? for a complete description of the advantages of using initialization lists.
If it's about best C++ practices, then:
Pass string parameters by const reference;
Use initializer list and initialize colour by passing it to parent constructor, not setColour.
The only thing I see off the bat is there is two printDetails() but the base class one is not virtual so you would not get the polymorphic behavior expected.
The main "issue" I see (and it is kinda minor) is that the derived constructor lets the parent class use its default colo(u)r value ("red"), and then supplies its own. That's kinda wasteful, when you could have given it the correct one from the get-go.
Rectangle::Rectangle(string col, int len, int br) : Polygon(col) {
length =len;
breadth=br;
};
Now, having done the above, you might as well intialize all the members that way:
Rectangle::Rectangle(string col, int len, int br)
: Polygon(col), length(len), breadth(br) {};
Hmmm. Now that I look at this, there's another thing wrong with it. Your constructors are passing in std::string objects by copy, and not modifying them. That's a waste too. All the constructor string parameters ought to be changed to string const & parameters. This potentially avoids an extra copy construction of a string at runtime, and notifies the compiler and the users that you aren't actually modifying the input strings (which is good practice when you in fact aren't).
So the final version would look more like:
Rectangle::Rectangle(string const & col, int len, int br)
: Polygon(col), length(len), breadth(br) {};
This formulation takes you from 4 std::string constructions (and 3 destructions) for every Rectangle constructor called down to 2. It can be further taken down to one by making the same change to the Polygon constructor.
You should call the base constructor with the col parameter:
Rectangle::Rectangle(string col, int len, int br) : Polygon(col)
{
//setColour(col);
length =len;
breadth=br;
}
Concerning the getArea():
The reason it doesn't compile when you remove it is because that function is marked as pure virtual in your Polygon class virtual double getArea()=0; using the =0;
For your PS regarding Rectangle::getArea(): the declaration in Polygon of virtual double getArea()=0; means that the function is a pure virtual function. You can think of this conceptually: "All polygons have an area, so I should be able to ask what it is, but unless the polygon has a particular type (square, circle), it won't know what its area is".
What this means is that your Polygon class is an abstract class. By not defining getArea() in the Rectangle class, your rectangle class is also an abstract class. You can't instantiate a Rectangle because the compiler doesn't know about any Rectangle::getArea() function definition.
You can also add call to the base class constructor in your initializer list:
Rectangle::Rectangle(string col, int len, int br)
: Polygon(col), length(len), breadth(br)
That uses the base class' constructor, so is a bit neater.
I can think of a number of possible problems here:
Use initializer lists to assign the values.
Call the base class constructor to set the color.
A string might not be the best type to represent a color. Maybe an enum or a separate color class would be better here. This also prevents passing invalid colors, if properly done.
Speaking of invalid values: length and breadth should be validated in the constructor (you don't want to end up with negative areas, do you?). At least use an assertion. It has no effect on release builds, but prevents development errors. For a more public interface, exceptions may also be an option (this is personal taste to some degree).
If you really want to use a string for the color, pass it by const reference (and probably test for edge cases like the empty string).
printDetails should probably be virtual, so you can call it with a base class pointer. The current implementation might not behave as intended.
The class seems to be designed for polymorphism. A virtual destructor has to be defined, if deletion from a base class pointer is required. Since there already is a virtual method, it probably won't hurt either.
getArea and printDetails should be declared const, so that they can be called on const objects. They shouldn't modify the object.
This is just a list of possibilities. Many of them depend on the intended usage of the class and might not be needed, but it doesn't hurt to consider them carefully.
As mentioned printDetails won't behave as expected.
I also think that just declaring getArea() within Rectangle class is kinda cheating because you do not provide implementation for it, and if you happen to call it within you code you would get a linker error.
An initialization order issue is possible. Polygon::setColour could call the pure virtual Polygon::getArea. (There is no indication that it would need to, but the possibility exists.) The implementation in Rectangle would presumably need length and breadth to compute the area, but they are not initialized yet.
The minimal fix is to initialize length and breadth before calling setColour:
Rectangle::Rectangle(string col, int len, int br)
{
length =len;
breadth=br;
setColour(col);
}
It would be best, of course, to drop the pure virtual getArea() declaration from Polygon because it doesn't appear to be needed by any Polygon methods. But that is outside of the scope of the question.