How to create an array of parameterized objects in C++? - c++

class book{
private:
int numOfPages;
public:
book(int i){
numOfPages = i;
};
};
class library{
private:
book * arrOfBooks;
public:
library(int x, int y){
arrOfBooks = new book[x](y);
};
};
int main()
{
library(2, 4);
};
With the example code above I would like to create a library of books that all have the same number of pages. So in the constructor of the library object, whenever a new book is created to be placed in the array I pass the argument in the parenthesis.
The above code when tested in C++ shell shows error: "parenthesized initializer in array new".
This is for the completion of a school project and no vectors are allowed (as it would be wise to do as I found doing my research) though I cannot think of any other ways to do it than the one shown above...

There is no syntax for initializing elements of a dynamic array using a non-default constructor.
You have to create the array first, then loop over the elements and assign each individually. Possibly the simplest way to do that is to use std::fill.

Array of books is a one dimensional array and it should be defined as follows:
library(int x)
{
arrOfBooks = new book[x];
};
If you have an assumption all books have same page you have pass it as a default parameter to your book class constructor:
book(int i=200)//set the defautlt value here
{
numOfPages = i;
};

Using templates:
#include <iostream>
template <int book_capacity> class book
{
private:
int numOfPages;
public:
book(): numOfPages(book_capacity){}
};
template <int lib_capacity, int book_capacity> class library
{
private:
book<book_capacity> arrOfBooks[lib_capacity];
int cnt;
public:
library(): cnt(0) {}
void addBook(book<book_capacity> b)
{
if (cnt < lib_capacity)
{
arrOfBooks[cnt] = b;
cnt++;
std::cout << "book is added" << std::endl;
return;
}
std::cout << "library is full" << std::endl;
}
};
int main()
{
library<2, 4> lib;
book<4> b;
lib.addBook(b);
lib.addBook(b);
lib.addBook(b);
lib.addBook(b);
system("pause");
return 0;
}

Related

How to store a reference to a C-style array in a class?

class Class
{
public:
Class(array[3][3]) //the constructor
{
this->array = array
}
array[3][3];
};
int main()
{
array[3][3] = {...initialization...};
Class object(array[3][3]);
}
I want to make an object, which uses the 2d array and modifies it. I know that C arrays are just pointers to an address, but I couldn't pass it in the constructor no matter how many *, & or [] I write.
The most clever thing I could think of is making an array of POINTERS in the class, and assigning each pointer, to the address of the original array's element via for loop, but then every time I want to modify, or read from the array in main, I have to write for example *array[2][1] = 3.
Any clever solution?
If I finally got the question correctly, you can use a reference to an array:
struct Class {
Class(int (&array)[3][3]) : array_(array)
{}
void set11(int value) {
array_[1][1] = value;
}
int (&array_)[3][3];
};
int main() {
int array[3][3]{};
Class object(array);
object.set11(99);
std::cout << array[1][1]; // Prints 99
}
If that's not what you want, please clarify your question.
Here's how to declare a pointer in your class that can point to the array in main.
class Class
{
public:
Class(int (*array)[3])
{
this->array = array;
}
int (*array)[3];
};
int main()
{
int array[3][3] = { ... };
Class object(array);
}

Defining an int array in a class C++

Is there any way to dynamically (I think that's the right term) define an int array in a class, the size of which is a private member variable in that same class? For example:
class Scene()
{
//public member functions
private:
int max;
int xcoords[max];
}
I've searched through other answered questions on here, but I haven't learned how to use vectors in class yet, which is what most responses suggest. Ideally, in my constructor for the class, I'd be passed an int max, with which I then initialize the xcoord array to have a size of max with entries all -1.
If you want dynamic sizing for your member data, you almost certainly have to store it in the heap. Which means, something like this
class Foo{
int* data;
public:
Foo(int size){
data = new int[size];
}
~Foo(){
// remember to clean up
delete[] data;
}
}
This way, your constructor will allocate size for size ints in the heap memory when the class is created, and free it up when it is deleted.
The more official c++ way of writing the constructor is:
Foo(int size):
data(new int[size])
{
}
But in the end it will do the same thing.
Consider leaving memory management to standard libraries.
Instead of Arrays, use vectors.
#include <vector>
#include <iostream>
using std::vector;
using std::cout;
using std::endl;
class Scene
{
public:
vector<int> verticeData;
};
int LEGACY_FUNCTION(const int * data, int count)
{
for (int i = 0; i < count; ++i)
{
cout << " ";
cout << data[i];
cout << " ";
}
cout << endl;
return 0;
}
int main()
{
Scene myscene;
myscene.verticeData.emplace_back(3);
myscene.verticeData.emplace_back(4);
myscene.verticeData.emplace_back(5);
LEGACY_FUNCTION(myscene.verticeData.data(), myscene.verticeData.size());
myscene.verticeData.clear();
myscene.verticeData.emplace_back(1);
myscene.verticeData.emplace_back(7);
LEGACY_FUNCTION(myscene.verticeData.data(), myscene.verticeData.size());
return 0;
}

access a class member based on a string

i want to write a function which takes in a vector of objects and name of one of their property. then it will do some manipulation based on the values of that property of the objects.finally will return an object.
eg.
class A{
Point center;
int length;
...
...
};
class B{
Point position;
bool value;
...
...
};
now if we pass the function a vector of type A, it should manipulate the objects based on the value of center; if we pass the function a vector of type B, it should manipulate the objects based on values of position.
functiona(vector<T>,string property)
inside the function how can i access a property based in the passed string property??
EDIT: the 2nd property being string is just for illustration; i don't care what type it is
Yes, it can be done using pointers-to-members. Example use:
#include <iostream>
#include <vector>
using namespace std;
class A {
public:
int a;
A(int x):a(x){}
};
class B {
public:
int b;
B(int x):b(x){}
};
template <typename T> int func(vector<T> data, int T::*pointer) {
int total = 0;
for (unsigned i = 0; i < data.size(); ++i) {
total += data[i].*pointer;
}
return total;
}
int main() {
vector<A> vec1;
vec1.push_back(A(123));
vec1.push_back(A(456));
vec1.push_back(A(789));
vector<B> vec2;
vec2.push_back(B(666));
vec2.push_back(B(666));
vec2.push_back(B(666));
cout << func(vec1, &A::a) << endl;
cout << func(vec2, &B::b) << endl;
return 0;
}
You declare a pointer-to-member as such: valueType class::*pointerName, read adresses as such: &class::field and use them like that: object.*pointerToMember or pointerToObject->*pointerToMember.

C++ Array Member of Constant Length (Initialisation of)

I have a class that contains an array. I want this array to be set at the length of a constant:
// Entities.h
class Entities
{
private:
const int maxLimit;
int objects[maxLimit];
int currentUsage;
public:
Entities();
bool addObject(int identifier);
void showStructure();
};
The main problem I'm having is with the constructor. I thought:
// Entities.cpp
Entities::Entities() : maxLimit(50)
{
currentUsage = 0;
cout << "Entities constructed with max of 50" << endl;
}
would have been sufficient...but not so. I don't know if I can use the initialiser list for array initialisation.
How can I initialise the objects array using the maxLimit const? I'm relatively new to classes in C++ but I have experience with Java. I'm mainly testing out this phenomenon of 'constness'.
The array must have a constant length. I mean a length that is the same for all objects of that class. That is because the compiler has to know the size of each object, and it must be the same for all objects of that particular class. So, the following would do it:
class Entities
{
private:
static const int maxLimit = 50;
int objects[maxLimit];
int currentUsage;
public:
Entities();
bool addObject(int identifier);
void showStructure();
};
And in the cpp file:
const int Entities::maxLimit;
I prefer to use an enumeration for that, because i won't have to define the static in the cpp file then:
class Entities
{
private:
enum { maxLimit = 50 };
int objects[maxLimit];
int currentUsage;
public:
Entities();
bool addObject(int identifier);
void showStructure();
};
If you want to have a per-object size of the array, then you can use a dynamic array. vector is such one:
class Entities
{
private:
const int maxLimit;
std::vector<int> objects;
int currentUsage;
public:
Entities();
bool addObject(int identifier);
void showStructure();
};
// Entities.cpp
Entities::Entities(int limit)
: maxLimit(limit), objects(limit), currentUsage(0)
{
cout << "Entities constructed with max of 50" << endl;
}
Best is to do as much initialization in the initialization list as possible.
You can use template argument if you need to set array size at compile time:
template<size_t maxLimit>
class Entities
{
int objects[maxLimit];
public:
Entities() {}
...
};
Entities<1000> inst;
to dynamically allocate the memory you may need to use the 'new' keyword like
objects would be defined like:
int * objects;
inside the constructor you would do:
objects = new int [maxLimit];
edit:
forgot to mention, you'll need to deallocate the array when you're done, probably in the destructor of the class.
delete[] objects;
const ints have to be initialized at declaration. If you don't know the value that it has to be at the time of declaration, you're going to have to adopt a different strategy.
You'll need to create the array in the constructor, while keeping a pointer outside. Is this what you want to do?
In your class :
private:
int maxLimit;
int* objects;
And outside:
Entities::Entities() : maxLimit(50)
{
currentUsage = 0;
cout << "Entities constructed with max of 50" << endl;
objects = new int[maxLimit];
}
Entities::~Entities()
{
delete [] objects;
}
If all objects have the same length, then length can be static. This makes it a constant integral expression allowed as an array bound:
class Entities
{
private:
static const int maxLimit = 50;
int objects[maxLimit];
int currentUsage;
//...
};
Remember that sizeof(Entities) is a valid expression. Each Entities object has that same size.
Use std::vector and you get the expected behaviour. No need to worry about pointers, copies, etc
#include <vector>
class Entities
{
private:
const int limit;
std::vector<int> objects;
public:
Entities(int a_limit)
: limit(a_limit), objects(a_limit)
{ }
void addObject(int identifier)
{
if (objects.size() == limit)
throw whatever;
objects.push_back(identifier);
}
};

initialize a const array in a class initializer in C++

I have the following class in C++:
class a {
const int b[2];
// other stuff follows
// and here's the constructor
a(void);
}
The question is, how do I initialize b in the initialization list, given that I can't initialize it inside the body of the function of the constructor, because b is const?
This doesn't work:
a::a(void) :
b([2,3])
{
// other initialization stuff
}
Edit: The case in point is when I can have different values for b for different instances, but the values are known to be constant for the lifetime of the instance.
With C++11 the answer to this question has now changed and you can in fact do:
struct a {
const int b[2];
// other bits follow
// and here's the constructor
a();
};
a::a() :
b{2,3}
{
// other constructor work
}
int main() {
a a;
}
Like the others said, ISO C++ doesn't support that. But you can workaround it. Just use std::vector instead.
int* a = new int[N];
// fill a
class C {
const std::vector<int> v;
public:
C():v(a, a+N) {}
};
It is not possible in the current standard. I believe you'll be able to do this in C++0x using initializer lists (see A Brief Look at C++0x, by Bjarne Stroustrup, for more information about initializer lists and other nice C++0x features).
std::vector uses the heap. Geez, what a waste that would be just for the sake of a const sanity-check. The point of std::vector is dynamic growth at run-time, not any old syntax checking that should be done at compile-time. If you're not going to grow then create a class to wrap a normal array.
#include <stdio.h>
template <class Type, size_t MaxLength>
class ConstFixedSizeArrayFiller {
private:
size_t length;
public:
ConstFixedSizeArrayFiller() : length(0) {
}
virtual ~ConstFixedSizeArrayFiller() {
}
virtual void Fill(Type *array) = 0;
protected:
void add_element(Type *array, const Type & element)
{
if(length >= MaxLength) {
// todo: throw more appropriate out-of-bounds exception
throw 0;
}
array[length] = element;
length++;
}
};
template <class Type, size_t Length>
class ConstFixedSizeArray {
private:
Type array[Length];
public:
explicit ConstFixedSizeArray(
ConstFixedSizeArrayFiller<Type, Length> & filler
) {
filler.Fill(array);
}
const Type *Array() const {
return array;
}
size_t ArrayLength() const {
return Length;
}
};
class a {
private:
class b_filler : public ConstFixedSizeArrayFiller<int, 2> {
public:
virtual ~b_filler() {
}
virtual void Fill(int *array) {
add_element(array, 87);
add_element(array, 96);
}
};
const ConstFixedSizeArray<int, 2> b;
public:
a(void) : b(b_filler()) {
}
void print_items() {
size_t i;
for(i = 0; i < b.ArrayLength(); i++)
{
printf("%d\n", b.Array()[i]);
}
}
};
int main()
{
a x;
x.print_items();
return 0;
}
ConstFixedSizeArrayFiller and ConstFixedSizeArray are reusable.
The first allows run-time bounds checking while initializing the array (same as a vector might), which can later become const after this initialization.
The second allows the array to be allocated inside another object, which could be on the heap or simply the stack if that's where the object is. There's no waste of time allocating from the heap. It also performs compile-time const checking on the array.
b_filler is a tiny private class to provide the initialization values. The size of the array is checked at compile-time with the template arguments, so there's no chance of going out of bounds.
I'm sure there are more exotic ways to modify this. This is an initial stab. I think you can pretty much make up for any of the compiler's shortcoming with classes.
ISO standard C++ doesn't let you do this. If it did, the syntax would probably be:
a::a(void) :
b({2,3})
{
// other initialization stuff
}
Or something along those lines. From your question it actually sounds like what you want is a constant class (aka static) member that is the array. C++ does let you do this. Like so:
#include <iostream>
class A
{
public:
A();
static const int a[2];
};
const int A::a[2] = {0, 1};
A::A()
{
}
int main (int argc, char * const argv[])
{
std::cout << "A::a => " << A::a[0] << ", " << A::a[1] << "\n";
return 0;
}
The output being:
A::a => 0, 1
Now of course since this is a static class member it is the same for every instance of class A. If that is not what you want, ie you want each instance of A to have different element values in the array a then you're making the mistake of trying to make the array const to begin with. You should just be doing this:
#include <iostream>
class A
{
public:
A();
int a[2];
};
A::A()
{
a[0] = 9; // or some calculation
a[1] = 10; // or some calculation
}
int main (int argc, char * const argv[])
{
A v;
std::cout << "v.a => " << v.a[0] << ", " << v.a[1] << "\n";
return 0;
}
Where I've a constant array, it's always been done as static. If you can accept that, this code should compile and run.
#include <stdio.h>
#include <stdlib.h>
class a {
static const int b[2];
public:
a(void) {
for(int i = 0; i < 2; i++) {
printf("b[%d] = [%d]\n", i, b[i]);
}
}
};
const int a::b[2] = { 4, 2 };
int main(int argc, char **argv)
{
a foo;
return 0;
}
You can't do that from the initialization list,
Have a look at this:
http://www.cprogramming.com/tutorial/initialization-lists-c++.html
:)
A solution without using the heap with std::vector is to use boost::array, though you can't initialize array members directly in the constructor.
#include <boost/array.hpp>
const boost::array<int, 2> aa={ { 2, 3} };
class A {
const boost::array<int, 2> b;
A():b(aa){};
};
How about emulating a const array via an accessor function? It's non-static (as you requested), and it doesn't require stl or any other library:
class a {
int privateB[2];
public:
a(int b0,b1) { privateB[0]=b0; privateB[1]=b1; }
int b(const int idx) { return privateB[idx]; }
}
Because a::privateB is private, it is effectively constant outside a::, and you can access it similar to an array, e.g.
a aobj(2,3); // initialize "constant array" b[]
n = aobj.b(1); // read b[1] (write impossible from here)
If you are willing to use a pair of classes, you could additionally protect privateB from member functions. This could be done by inheriting a; but I think I prefer John Harrison's comp.lang.c++ post using a const class.
interestingly, in C# you have the keyword const that translates to C++'s static const, as opposed to readonly which can be only set at constructors and initializations, even by non-constants, ex:
readonly DateTime a = DateTime.Now;
I agree, if you have a const pre-defined array you might as well make it static.
At that point you can use this interesting syntax:
//in header file
class a{
static const int SIZE;
static const char array[][10];
};
//in cpp file:
const int a::SIZE = 5;
const char array[SIZE][10] = {"hello", "cruel","world","goodbye", "!"};
however, I did not find a way around the constant '10'. The reason is clear though, it needs it to know how to perform accessing to the array. A possible alternative is to use #define, but I dislike that method and I #undef at the end of the header, with a comment to edit there at CPP as well in case if a change.