C++ : Using an array in a nested class definition (OOP) - c++

So I am trying to define a class and I am using another array of a different class to define it.
//header file for Name.h
class Name {
string last;
string first;
};
//header file for Depositor.h
class Depositor {
Name name;
string ssn;};
//header file for Account.h
class Account {
Depositor depositor;
int acctnum;
string type;
double balance;
};
//header file for Bank.h
#include "Account.h"
class Bank {
Account account[]; //is this possible?
int active_accts;
};
When I am writing the cpp file I am running into a lot of problems!
//example of mutator
void Bank::setLastname(string lastname)
{
account.setLastname (lastname);
}
I didn't include the mutators and acessors that I wrote into the header file, but they are there and are public -- it won't compile.
Can you help? Is it even valid to use an array of a class in Bank.h?

Is it even valid to use an array of a class in Bank.h?
Yes, but it has to have a fixed dimension, e.g.,
Account account[3];
A type always has a fixed size in C++, and since an array member variable forms part of the class's size, you need to specify how many elements are in the array.
If you don't know how many elements you are going to need, you can use a sequence container:
std::vector<Account> account;

Account is not a nested class of Bank. Bank has a member data instance of type Account array.
You can have a primitive array member in a class, but you must specify the size of the array in the class definition: Account account[42];. The reason is that when you #include the class definition in another compilation unit, and then instantiate an instance of the class, the compiler needs to know what the size of that instance is.
It would be a wise idea to use std::vector<Account> rather than a primitive array. std::vector doesn't require committing to a particular size at construction; it grows dynamically. How come a std::vector doesn't require a size in the class definition, while a primitive array does? A std::vector holds as member a pointer to the elements on the heap. So the compiler does know the size of a std::vector; it uses the size of the pointer rather than the count of the elements.

By declaring the value of the array in the header file and by adding a variable in the .cpp file you can solve all the problems and leave it as an array.
//header file
class Bank {
Account account[100];
int active_accts;
public:
//mutator
void setLastname (string,int);
};
//the implementation file
void Bank::setLastname (string last, int index)
{
account[index].setLastname(last);
}
this will solve all your problems

account is an array of Accounts, which means you would need to do something like account[0].setLastname(lastname);

Instead of arrays, consider using vectors.
#include <vector>
// ...
class Bank {
std::vector<Account> accounts;
int active_accts;
};

you can't call setLastname(lastname) on the whole array. You need to call it on a specific instance of the Account class inside the array, like this: account[0].setLastname(lastname);
On another note, you really should be storing an array of pointers to Account objects.

Related

Get the name of an instance of a class in C++?

Lets say we have this class
class IntArray {
string name;
};
and we have this driver
int main(){
IntArray xe;
return 0;
}
Basically, how would we store that name of the instance, the "xe" through the constructor and into the data member "string name"?
C++ does not support doing this. Variable names are only something you as a developer are aware of. The compiled program doesn't have them. Your std::string name field inside the class IntArray would not hold "xe"; it would just be uninitialized.
You could, however, use a map - an std::unordered_map<std::string, IntArray> arrays to be exact - and then use arrays["xe"] to access the array you like using a runtime-defined string. See std::unordered_map on CPPReference for details.
#include <string>
class IntArray
{
std::string name;
public:
IntArray(std::string name) : name{ std::move(name) } {}
};
int main()
{
IntArray xe{ "xe" };
}
Well, you have some trick to solve your problem. Instead of using directly the constructor, just use a macro, like:
#define DECL(x) x(#x)
in some common header you #include in your application. Instead of declaring
IntArray ex;
do
IntArray DECL(ex);
on expansion, you will get something like:
IntArray xe("xe");
you can also use the variadic macro expansion of latest standards to be able to call a different constructor.
#define DECL(name, ...) name(#name, #__VA_ARGS__)
If you want, you can also include the type in the macro, so:
#define DECL(type, name) type name(#type, #name)
and declare your variable with:
DECL(IntArray, ex);
That will expand to:
IntArray ex("IntArray", "ex");
this trick is far from complete, but can help you to avoid mistakes because of mispelling variable names as a consequence of having to write twice in source code.

Calling a struct in a class from main in C++

I have a header file with a class and a struct in it, but I can't figure out how to call it from main.
class TestDetails {
public:
struct User{
std::string username;
std::string password;
};
};
How do I call the following from main,and store a struct into a vector so I can
pass into a text file?
If by "calling a struct" you mean instantiating it, then knowing that the type is TestDetails::User, you simply need to create a vector<TestDetails::User>. Then you can fill it up with objects like you would do with any other type. For example,
// instantiate a vector with two users
std::vector<TestDetails::User> v{{"bob", "1234"},
{"alice", "alice_psswd"}};
// add another user
v.push_back({"trudy", "****"});

Can't use a class that is defined in another hpp file

I'm having a little problem trying to use my "gameAux" class in "userAux.hpp" file I made.
Here are the two hpp files I made.
I marked the place where I get an error.
userAux.hpp:
#include "gameAux.hpp"
class userAux{
int gameId;
int userId;
int rate;
gameAux aGame; <---error: ‘gameAux’ does not name a type
};
gameAux.hpp:
#include "userAux.hpp"
class gameAux{
int gameId;
userAux aUser; <--- OK
};
I'll be very happy if someone could point out what's the problem :)
You cannot have one class include an instance of another class, and have that other class include an instance of the first class. That's an infinite recursion and obviously cannot work.
The answer is to use pointers and forward declarations.
class gameAux; // forward declaration
class userAux{
int gameId;
int userId;
int rate;
gameAux* aGame;
};
class gameAux{
int gameId;
userAux* aUser;
};
When two classes depend on each other like this I would be tempted to place them both in the same header file. However if you want separate header files then you could forward declare each class in the other classes header file. That way neither header file needs to include the other.
Your problem is that both of your classes depend on each other. When the compiler goes to see how much space it needs to reserve for gameAux objects, it says 'ok, I need an int and a userAux to fit in there'. So the next question is, how much space does it need for ints and userAux objects?
Then when it tries to figure out how much space it needs for a userAux object, it says 'ok, three ints and a gameAux object'... and there's the problem. It's going to keep going back and forth between those two files, trying to figure out how much space it needs for each thing, and never be able to figure it out.
To solve this, you need to make one of your classes depend on a reference or pointer to the other class. Since references and pointers always take up the same amount of space on a given system, the compiler will be able to allocate space for a userAux if it sees this:
class gameAux;
class userAux{
int gameId;
int userId;
int rate;
gameAux &aGame; // or gameAux *aGame; // <---error: ‘gameAux’ does not name a type
};
and then it will have a fine time allocating space for both of the objects, no problems ^^
EDIT: Also, you won't need to #include the header file for gameAux any more at the top of userAux.hpp - just forward-declare gameAux like so at the top of the file: class gameAux.
You don't need to include the entire class definition. You can avoid a circular dependency by just forward declaring, and using a pointer:
#include "gameAux.hpp"
class gameAux; // forward declaration
class userAux{
int gameId;
int userId;
int rate;
gameAux *aGame;
};
and vice versa in the other file. Then #include the appropriate hpp header in the implementation source file for each class.

C++: cannot assign vector of pointer to another vector of pointer

I have class Student (studentOwner) and class Section.
Here is my class Student:
class Student {
vector<Section*> enrolledSections;
public:
vector<Section*> getEnrolledSections() const { return enrolledSections; }
}
So, when I get vector<Section*> and assign to another vector, I will meet error. I'm using Microsoft Visual Studio.
// first example: no error, if take size of vector
int a = studentOwner->getEnrolledSections().size();
// second example: error, when only take its vector and assign again
// Error: no suitable user-define conversion from "std::vector<error-type" ....
vector<Section*> enrolled = studentOwner->getEnrolledSections();
// third example: error when take this vector and assign to reference of same type
// Error: initial value of reference to non-const value must be lvalue
vector<Section*>& enrolled = studentOwner->getEnrolledSections();
Full error at second example is:
Error: no suitable user-define conversion from "std::vector<error-type", std::alocator<<error-type> *>> "to " std::vector<Section*, std::allocator<Section*>>" exists
In many class of my project, I cannot do line two and line three and received same error. I cannot explain by myself. Please teach me at this point.
Thanks :)
Usually if you see error-type in MSVC errors, it's a result of a forward declared type that wasn't included in time for that compilation unit. For example,
// Course.h
class Student;
class Course {
[...]
public:
Student* getStudent();
}
// Course.cpp
#include "Course.h"
Student* Course::getStudent()
{
return new Student("Name"); //< Whoops, we never included Student.h!
}
In the comments you indicate a circular include dependency. As #Daniel Castro noted, you should forward declare in your header files to avoid the circular includes, then include the needed header files in your .cpp files (note the forward declaration class Student; above if you're not familiar).
As an aside, I would also note some design issues with your example. Returning std::vector<Section*> doesn't tell much about who owns what. If I get a std::vector by value from a function, the convention is that I now own the vector and its contents. If I own something, then I'm responsible for deleting it. Without seeing your actual implementation, most coders would be surprised to learn they shouldn't delete the contents of the vector. I would suggest either returning the vector by const& (eg, const vector<Section*>&) which prevents client code from manipulating the vector (so clients don't own it), or using std::shared_ptr to manage a shared ownership scheme of your Section objects:
class Student {
vector<shared_ptr<Section>> enrolledSections_;
public:
vector<shared_ptr<Section>> getEnrolledSections() const { return enrolledSections_; }
}
Now it's clear who owns what. More than you were asking for, but hopefully it helps.
you need to return the vector as a reference, otherwise the vector is copied on return. Also your function is const, so you have to return the vector as const too.
class Student
{
std::vector<Section*> enrolledSections;
public:
const std::vector<Section*> &getEnrolledSections() const { return enrolledSections; }
}
now you should be able to
const std::vector<Section*>& enrolled = studentOwner->getEnrolledSections();

How to place into an array of addStaff(const Staff&)

I do not understand how to implement the following code to allow the function to write into the existing array.
void Project::addStaff(const Staff&)
{
//add employees into staff array
}
having (const Staff&) as parameters is new to me as it does not create an object anyways. I can not change it because it is to be used as is to implement the program correctly. the Staff constructor is as follows
Staff::Staff (std::string lname, std::string fname)
: theLname(lname), theFname(fname)
{}
Is there a way to write the variable for staff so I can access the needed values to place into the array? Any help would be greatly appreciated!
Your Project class may have a std::vector data member, and you can use vector.push_back() method to add new Staff instances in the array:
// Inside Project class:
std::vector<Staff> m_staffPersons;
void Project::addStaff(const Staff& newStaff)
{
// Add employees into staff array
m_staffPersons.push_back(newStaff);
}
I would define std::vector<Staff> representing list of employees as a member of this Project class:
class Project
{
public:
void addStaff(const Staff&);
vector<Staff> employees;
}
Then your addStaff method could look like this:
void Project::addStaff(const Staff& newEmployee)
{
employees.push_back(newEmployee);
}
But I would definitely rename class Staff since it doesn't say much about itself. Employee would be much better name for this class.