How to access struct variables within a class, inside a different class? - c++

I have multiple files for each class. I'm trying to use data from a struct (inside the first class) and use it in the second class.
I've tried putting the struct in its own file, but this felt a bit unnecessary. I've tried a few different ways of coding it out, such as declaring the struct in main and also declaring the struct in the other class.
// class 1
class Shop
{
public:
struct Products
{
int price;
int quantity;
};
void SetProductValue();
private:
float register_total;
};
// class 2:
class Consumer
{
public:
Shop Products;
int total_customers;
bool buy_product(); // <--
for this?
private:
string consumer_name;
float Consumer_balance;
};
What does the function description look like for void buy_product()?
bool Consumer::buy_product();
{
if (consumer_balance < Products.price) return false;
if (consumer_balance >= Products.price) return true;
}
This is one of several ways I've tried, and I get errors for trying to do Products.price

struct Products { ... }; declares a type, not a product instance.
In order to have an actual product in your class, you have to declare a member variable:
class Shop
{
public:
struct Product // no need for "s"
{
int price;
int quantity;
};
void SetProductValue();
private:
// either:
Product product; // <--- HERE
// or, if your shop has multiple products:
std::vector<Product> products;
float register_total;
};
In order to access one specific product (which one?), your Shop class has to expose some accessor functions. An option is to select a product by name:
Product Shop::GetProductByName(const std::string& name) const
{
// find right product _instance_ here
}

Related

I have problem with least privilege principle. incrementing a member when an object is created

I want to keep track of the number of students in my system so, My idea was to make a static datamember in the "StudentController" class called "_numOfStudents" and increment it with the Student's constructor but it didn't work so, I moved it into the "Student" class and made that when a Student object is created the number increment by the help of the constructor. The problem is: isn't it not the Student class's business to know how many students are there thus breaking the principle of least privilege. what can I do better to keep track of the student objects' count.
Student(string firstName, string lastName, int age,vector<float>&subjects)//Student conctructor
{
SetFirstName(firstName);
setLastName(lastName);
SetAge(age);
SetMarks(subjects);
this->m_id++;
StudentController::_numberOfStudents++;
}
class StudentController//this is where i declared the static data member
{
private:
list<Student> _students;
public:
static int _numberOfStudents;
StudentController() {};
StudentController(list<Student>& st) :_students(st) {};
}
}
};
int StudentController::_numberOfStudents = 0;
When you try to do StudentController::_numberOfStudents++; in the constructor, the StudentController class is not yet defined, therefore the compiler doesn't know about that class and its static member.
Maybe keeping track of the students shouldn't be the role of the Student class itself. Instead it should be the role of a separate Classroom object:
struct Student;
struct Classroom {
void add(Student&) {
m_count++;
}
size_t count() const { return m_count; }
private:
size_t m_count{0};
};
struct Student {
Student(Classroom& classroom) {
classroom.add(*this);
}
};
int main()
{
Classroom classroom;
Student alice{classroom};
Student bob{classroom};
assert(classroom.count() == 2);
}

What is the best way to implement static variables per class child? [C++]

In my code, I want all children of class Component to have a unique ID that is only shared per their own instances. Right now, I'm implementing such a system like so:
template <class componentType>
struct Component {
static unsigned int ID;
};
Example component:
struct Transform: public Component<Transform> {
float x, y, z;
};
The ID is assigned using another method. The issue is that I want to have a vector of components as a member variable of another Entity class. Additionally, I want said class to have the functions AddComponent() and GetComponent(). Right now, such an implementation requires that I make both functions templates- this creates a variety of problems in both having to explicitly instance each version of the functions, and in generating a lot of unnecessary code when the only member variable accessed in these functions is the ID, which I know to be common in all Component templates.
I could implement a virtual function that is overriden by every child of Component, but that would require I copy code for each and every child, as well as couple the ID system with the unrelated component children, which seems like bad practice. What is the best way to assign unique IDs to the children? If it's with templates, then how can I bypass the problem with methods that use the class?
What you could do is to let Component inherit from Component_base and that this class has a virtual function get_id which is implemented by Component:
#include <iostream>
namespace {
static unsigned int next_id = 0;
template<typename T>
unsigned int get_type_id() {
static unsigned int id = ++next_id;
return id;
}
}
struct Component_base {
virtual unsigned int get_id() = 0;
};
template <class componentType>
struct Component : public Component_base {
virtual unsigned int get_id() {
return Component::ID;
}
static unsigned int ID;
};
template <class componentType>
unsigned int Component<componentType>::ID = get_type_id<componentType>();
struct Transform: public Component<Transform> {
float x, y, z;
};
struct Transform2: public Component<Transform2> {
float x, y, z;
};
int main() {
Transform t1;
Transform2 t2;
std::cout << t1.get_id() << std::endl;
std::cout << t2.get_id() << std::endl;
return 0;
}

Inheriting static variable in classes?

Given an abstract class called Job and other classes that inherit it like Teacher, Worker ,etc...
I want those classes to inherit something like a static variable -I'm saying like since it's not allowed to inherit static according to what I read- for Job (Like Salary) with different values for each class, how may I do that?
Until now, in the c'tor for Teacher I have created a local variable for each object called salary such that it's equal to 100, but that doesn't seem smart since all teachers have the same salary according to what I'm working on.
For example:
class Job{
int salary;
std::string tag;
public:
Job(int salary,std::string tag;) : salary(salary), tag(tag)
{}
};
class Teacher: public Job{
public:
Teacher(std::string tag) : Job(100,tag){}
};
class Worker: public Job{
Worker(std::string tag) : Job(200,tag){}
};
every worker has salary=100 but I want this to be related to the class worker and not for each object. (I can define this as static for each class but again it doesn't seem smart to declare the same static value in 100 classes the inherit a one which has that static value)
I hesitate to post this answer, because I think the code as posted is just fine, but if you really want to eliminate the salary variable, then you can do this:
class Job
{
...
virtual int GetSalary () = 0;
};
class Teacher : public Job
{
...
int GetSalary () override { return 100; }
};
class Worker : public Job
{
...
int GetSalary () override { return 200; }
};
A similar scheme can be used to get rid of tag (and, for that, this approach might actually be warranted).
You could also make use of templates, they are evaluated at compile-time so you won't have performance overhead:
template <int Salary>
class Job{
std::string tag;
public:
static const int salary = Salary;
Job(std::string tag) : tag(std::move(tag)) {
}
};
class Teacher: public Job<100>{
public:
Teacher(std::string tag) : Job<100>(std::move(tag)) {
}
};
class Worker: public Job<200>{
Worker(std::string tag) : Job<200>(std::move(tag)) {
}
};
and you can just get the salary from plain old Teacher::salary, Worker::salary, Job<N>::salary, etc.
I am not sure if this is more software design. Anyway, I will give you feedback for the current design and what you could do (still using public inheritance).
The code you currently have is fine. It is flexible, since you can actually set a specific salary per object.
But, of course, you are paying for the flexibility - for each object, you will have a maybe unnecessary member, since it should already be known by the type.
If you want the flexibility to have classes with same salary, and classes with specialized salaries, you can extend your hierarchy a bit:
class IJob{
public:
virtual double getSalary() = 0;
};
// Teachers always have the same salary
class Teacher: public IJob{
static constexpr double salary = 200; // named constant, not strictly necessary. But it can make it more readable.
public:
double getSalary virtual() { return salary; }
};
// Worker always have the same salary
class Worker : public IJob{
static constexpr double salary = 100;
public:
double getSalary virtual() { return salary; }
};
// A base class for workers having different salaries
class SalarizedJob : public IJob
double salary;
public:
SalarizedJob(double salary) : salary(salary) {}
double getSalary() override { return salary; };
};
// Greedy bankers always want more salary than their coworker
class Banker : public SalarizedJob
{
public:
Banker(double salary) : SalarizedJob(salary) {}
};

Is there a way in C++ to restrict a function of a given class to another class only(without using inheritance, friend)?

I want to design a class having a function which should be restricted to be called from another class only. Specifically, in the given code
class Club
{
int id;
string name;
vector<string> members;
int generateId()
{
static int i=1;
return i++;
}
public:
Club(string name) { this->name = name; this->id = generateId(); }
void registerMember(string memberName) { members.push_back(memberName); }
int getId() { return id; }
};
class Application
{
vector<Club> clubs;
public:
void registerClub(Club &club) { clubs.push_back(club); }
void addMemberToClub(int clubId, string memberName)
{
for(Club club: clubs)
{
if(clubId == club.getId())
club.registerMember(memberName);
}
}
};
An user(public user) can create an object of the class Club and register using the function registerMember() since it's public. I want the user to register via an object of the class Application, using the addMemberToClub() function only. If the user goes by the former way mentioned, I can't keep track of the user. Is there a way to enforce the latter?
I don't want to use the access modifier protected since inheritance has no meaning here.
I don't want to use the friend keyword, since it's considered bad practice.
Here is a "lock-and-key" way to permit another class (and only that class) or even a single function in another class to access just one member function, unlike friend which exposes all private members at the same time:
#include <iostream>
class Key;
class Locked
{
static const char* const Greeting;
public:
static Key secretive();
static void attacker();
};
struct Admin
{
void doit();
};
class Key
{
~Key() = default;
//friend class Admin;
friend void Admin::doit();
friend Key Locked::secretive();
};
void Admin::doit()
{
Locked::secretive();
std::cout << Locked::Greeting; // compile error
}
constexpr const char* Locked::Greeting = "Hello!\n";
Key Locked::secretive()
{
std::cout << Greeting;
return Key();
}
void Locked::attacker()
{
std::cout << Locked::Greeting; // ok, it's just private
Locked::secretive(); // compile error, it's locked down tight
}
int main()
{
Admin a;
a.doit();
std::cout << Locked::Greeting; // compile error
Locked::secretive(); // compile error
}
It also works around the "which class is declared first?" problem that prevents two classes from mutually friending individual member functions of each other, because the restricted operation needs to follow only a forward declaration of the key type; the full definition of the other type can (and in this example does) appear above the key definition, allowing individual members to be named in the key type's friend directive.
Note that in this solution the "obvious" fact that other members of the same class can access the locked function is NOT true. The compiler prevents Locked::attacker() from calling Locked::secretive().
Note also that I've used static in this example to minimize the number of objects I had to create, but the approach works just fine for non-static member functions too.
A potentially MUCH easier way to restrict what part of the program can call your protected function is with a simple flag:
class Application
{
static bool addingMember = 0;
public:
static bool isRegistrationOk() { return addingMember; }
void registerClub(Club &club) { clubs.push_back(club); }
void addMemberToClub(int clubId, string memberName)
{
addingMember = true;
for(Club club: clubs)
{
if(clubId == club.getId())
club.registerMember(memberName);
}
addingMember = false;
}
};
void Club::registerMember(string memberName)
{
assert(Application::isRegistrationOk());
members.push_back(memberName);
}
Much easier to grok, but it's a runtime check not compile-time, and requires additional work to be made thread-safe. But it accomplishes the goal with no usage of friend or inheritance.
friend is an appropriate mechanism to use in this case. Make registerMember private in Club, and Club can grant friendship to Application:
class Club
{
// ...
void registerMember(string memberName) { members.push_back(memberName); }
public:
// ...
friend class Application;
};
Now only Application can call registerMember, and Club as well, of course.
Here's a demo.

C++ calling multiple constructors

I am trying to accomplish the following: I have 4 classes(lets call one primary, other 3 secondary ones) within one namespace, I want to store instances of secondary classes as private members of primary, to do this I need to call secondary constructors from primary's one and then store instances. But Unfortunately I do not completely understand how to do it (not really experienced with c++): here is what I have in header file:
class secondary_one
{
private:
int number1;
public:
secondary_one(int);
int get_number1() const;
};
class secondary_two
{
private:
int number2;
public:
secondary_two(int);
int get_number2() const;
};
class secondary_three
{
private:
int number3;
public:
secondary_three(int);
int get_number3() const;
};
And 'primary' class is:
class primary
{
private:
secondary_one one;
secondary_two two;
secondary_three three;
public:
primary(int,int,int);
};
Upon calling primary constructor I want first argument to be send to constructor of secondary_one, second argument to constructor of secondary_two and so on.
And then store instances as private members. Is it even possible or I am just wasting time? If it is, can you give a short example what should I have in header and source file?
Use the constructor initialization list:
class primary
{
public:
primary(int a, int b, int c) : one(a), two(b), three(c) {}
private:
secondary_one one;
secondary_two two;
secondary_three three;
};