Child Class constructor using private member - c++

I have multiple child classes extending the base class (Media).
When I call the child classses constructor, I am not able to use the private member mBookLateFee's value to do some calculations .. it appears to be using the default 0.0 and not the members contents.
However, if I put the actual value of 1.25 in there it works..
When constructed can the object not initialize from a child classes member?
class Media {
private :
string mCallNumber;
protected:
string mStatus;
string mTitle;
string mType;
int mDaysOverDue = 0;
double mDailyLateFee = 0.0;
double mTotalLateFees = 0.0;
public:
Media(string status, string title, int days=0, string callNum="", string type="", double fee=0.0) : mStatus(status),
mTitle(title), mDaysOverDue(days), mCallNumber(callNum), mType(type), mDailyLateFee(fee) {};
~Media(){};
void setCallNo(string newCallNum);
string getCallNo();
void setHowLate(int numDays);
int getDaysOverDue();
virtual void print();
virtual double getFees() = 0;
};
class Book : public Media {
private:
double mBookLateFee = 1.25;
protected:
string mAuthor;
int mNumPages;
public:
Book(string status, string title, int days, string callNum, string author, int pages=0) :
Media(status, title, days, callNum, "Book", mBookLateFee), mAuthor(author), mNumPages(pages){
mTotalLateFees = mDaysOverDue * mDailyLateFee;
};
double getFees() { return mTotalLateFees;}
void print();
};

The superclass, the parent class, gets constructed before the child class.
When your child class invokes the superclass's, the parent class's constructor, the child class has not been constructed yet. It's mBooklateFee is not yet constructed.
In a manner of speaking, it does not exist yet. Hence, you cannot use it in order to invoke the parent class's constructor.

Related

Explicitly initalize abstract base class constructor with value determined by parameter of derived class constructor

Within my vehicle base class, I have a private member variable, string type (for type of vehicle, ie car, motorbike, tricycle, etc).
#pragma once
using namespace std;
#include <string>
#include <iostream>
class vehicle {
public:
vehicle(string reg, string make, string model, int age, string type);
virtual ~vehicle() = default;
virtual double costPerDay() = 0;
protected:
int age;
int perDayCostCap(int costPD);
double penceToPounds(int pence);
private:
const string type;
string const reg, make, model;
};
One of the derived classes, bike, has a numberOfWheels variable which is to be passed into its constructor. I want to initialize the base class constructor with type bicycle or tricycle depending on the numberOfWheels.
I can not figure out how to achieve this, seeing as the base class constructor has to be initialized before the function body of the child class.
The following shows what I would like to achieve (though, I know this is not possible):
bike::bike(int engineCC, int numOfWheels, string reg, string make, string model, int age)
:engineCC(engineCC), numOfWheels(numOfWheels) {
string tricOrBic = (numOfWheels == 2) ? "bicicle" : "tricicle";
vehicle:reg=reg, make=make, model=model, age=age, type=tricOrBic;
};
Like this?
bike::bike(int engineCC, int numOfWheels, string reg, string make, string model, int age)
: vehicle(reg, make, model, age, numOfWheels == 2 ? "bicycle" : "tricycle")
, engineCC(engineCC)
, numOfWheels(numOfWheels)
{
}
This is normal programming, maybe you had some problem I'm not seeing.

Constructor in double inheritance

I have a problem with my constructor. I have class vehicle, then I made class motorVehicle which inherited after vehicle and then I want to make class motorcycle which inherits after class motorVehicle and I can't make my default constructor because I have error:
Class vehicle and motorVehicle isn't changed by me and class motorcycle is in 2 option none of these option works but I give you both of them. Btw the problems are (First option): no matching constructor for initialization of 'motorVehicle' and with second option expected ; after expression and expected member name or ; after declaration specifiers
class vehicle {
public:
int numberOfWheels;
string color;
float vehiclePayload;
vehicle(): numberOfWheels{4},color{"black"},vehiclePayload{500}{
}
};
class motorVehicle : public vehicle {
public:
float tankCapacity;
float fuelConsumption;
float mileage;
float currentAmountOfFuel;
int yearOfProduction;
unsigned long long int vin;
motorVehicle(): tankCapacity{30}, fuelConsumption{6}, mileage{100}, currentAmountOfFuel{10}, yearOfProduction{2021}, vin{1}, vehicle{4, "black", 500} {
}
};
class motorcycle : public motorVehicle{
public:
float bootSize;
string brand;
string model;
motorcycle(): bootSize{500}, brand{"Ninja"}, model{"Kawasaki"}, motorVehicle{30,6,100,10,2021,1,vehicle{4, "black", 500}}{
}
};
class motorcycle : public motorVehicle{
public:
float bootSize;
string brand;
string model;
motorcycle(): bootSize{500}, brand{"Ninja"}, model{"Kawasaki"}, motorVehicle(){30,6,100,10,2021,1,vehicle{4, "black", 500}}{
}
};
Your base classes do not declare any constructor taking actual values. As these classes do declare a default constructor, aggregate initialisation doesn't work: there is a declared constructor, i.e., the class isn't an aggregate. If you want to directly initialise the base class you could use their implicitly generate copy constructor, though. However, you'd still need to populate the content of the class separately as you'll need to created the object using a default constructor:
class motorVehicle : public vehicle {
public:
float tankCapacity;
float fuelConsumption;
float mileage;
float currentAmountOfFuel;
int yearOfProduction;
unsigned long long int vin;
motorVehicle(): tankCapacity{30}, fuelConsumption{6}, mileage{100}, currentAmountOfFuel{10}, yearOfProduction{2021}, vin{1},
vehicle([]{
vehicle rc;
rc.numberOfWheels = 4;
rc.color = "black";
rc vehiclePayload = 500;
return rc;
}()) {
}
};
Obviously, instead of using a lambda function you could have a factor function, let's say makeVehicle(int wheels, std::string const& color, float payload) appropriately initialising the members. There should really be a suitable constructor for vehicle, though.

How do I convert an object of Class B to Class C, if both Class B and C are derived of Class A in C++?

I have a base class called "Customer", and 2 derived classes "RegularAccount" and "VipAccount".
Now, I want to implement a "promote" member method, that allows RegularAccount to be promoted to VipAccount if it meets some condition.
How can I do this in C++? I tried to call a constructor inside the "promote" method of RegularAccount but was unable to do so. Is there a way to copy all data from RegularAccount's object to VipAccount's object in a member function of RegularAccount?
Here is the structure of my RegularAccount class:
class RegularAccount : public Customer {
private:
public:
// Constructors && Destructors
RegularAccount();
RegularAccount(string id, string name, string address, string phoneNumber, int numberOfRental);
~RegularAccount();
// Member functions
void rentItem(const string itemName);
void returnItem(const string itemName);
void details();
void showRentalList();
void promote();
};
VipAccount class:
class VipAccount : public Customer {
private:
int rewardPoints;
int freeRentItemAwarded;
public:
// Constructors
VipAccount();
VipAccount(string id, string name, string address, string phoneNumber, int numberOfRental);
// Member functions
void rentItem(const string itemName);
void returnItem(const string itemName);
void checkRewardPoints();
void details();
void showRentalList();
void promote();
};
Derive VipAccount from RegularAccount, makes sense cause Vip should have everything Regular has. Write a constructor for VipAccount which accepts an instance of RegularAccount as argument. In constructor pass the argument to the base class RegularAccount. To promote ,create an instance of VipAccount with RegularAccount as argument, delete instance of RegularAccount afterwards

How to access derived class member function using Base class function?

I am trying to design a parking system (Low-level Design )
Some classes behave like this.
class Vehicle
{
public:
int entryTime;
int exitTime;
virtual void leaveParking(Vehicle*);
virtual int getChargePerHr();
//virtual void getChargePerHr() = 0;
Vehicle() {}
};
class Car : public Vehicle
{
private :
int chargePerHr = 30;
public:
void leaveParking(Vehicle*);
int getChargePerHr();
Car(){}
};
class Bike : public Vehicle
{
private :
int chargePerHr = 10;
public:
void leaveParking(Vehicle*);
int getChargePerHr();
Bike(){}
}
void Vehicle ::leaveParking(Vehicle* v)
{
int pay = v-> // Here expecting Car class member function getChargePerHr() should come
//so that I can access private member chargePerHr of car class.
// But I am not able to access the Car class member function here.
}
int main()
{
Car c1; // assume Car c1 has already parked.
Vehicle v;
Vehicle* vptr = new Vehicle();
vptr = new Car();
c1.leaveParking(vptr); // Car c1 wants to leave the parking place
}
I want to access getChargePerHr() of Car class using Base class Vehicle member function.
I tried with pure virtual function but still could not make it.
Could anyone help me?
Problem
Here:
void Vehicle::leaveParking(Vehicle* v)
{
...
}
You're not able to access Car::getChargePerHr() because v is a Vehicle not a Car.
Clearly you're attempting to achieve polymorphism since it appears you want derived classes of Vehicle to perform the same actions when they leave parking.
Solution
Declare Vehicle::getChargePerHr() as pure virtual (or virtual if you want a default implementation)
Provide implementations of getChargePerHr() in your derived classes
Implement Vehicle::leaveParking() using just the methods you've defined in Vehicle
At runtime, the virtual table will resolve overrides and call the correct derived implementation.
Other Issues
You are inheriting from Vehicle without declaring its destructor virtual. This means if any child classes need to perform clean-up, their destructors won't be called.
You're missing a semicolon after the Bike class declaration.
If every Vehicle does the same thing when leaving parking, it doesn't make sense to have leaveParking() be virtual—you make a member function virtual if you want it to be able to be overridden by child classes.
Vehicle::leaveParking() should probably not be taking another Vehicle as a parameter. The function acts on the vehicle itself, not on a different one.
If your constructor is empty, it's better to leave it out of the class declaration since it can confuse others who might read your code.
And many more issues. I suggest you take aalimian's advice to read up on C/C++. Your code shows many misunderstandings.
Code
Putting everything together, here's an example:
class Vehicle
{
public:
int entryTime;
int exitTime;
virtual ~Vehicle() = default;
void leaveParking();
virtual int getChargePerHr() = 0;
};
void Vehicle::leaveParking()
{
// This will call a derived class's implementation
int pay = getChargePerHr();
// Do more vehicle stuff
}
class Car : public Vehicle
{
private:
int chargePerHr = 30;
public:
int getChargePerHr() override;
};
int Car::getChargePerHr()
{
return chargePerHr;
}
class Bike : public Vehicle
{
private:
int chargePerHr = 10;
public:
int getChargePerHr() override;
};
int Bike::getChargePerHr()
{
return chargePerHr;
}
You can see this in action here.

Define getter for child class variable inside parent

I have a project where I am accessing several classes using a pointer to a parent class. I need to know which child class the pointer is referring to, so I am adding a distinct integer ID number to each of them as a constant class variable.
I need to access this variable using the pointer, so I wrote a getter function for that variable. Since the code for the getter function would be the same for all of the child classes, I tried defining the function in the parent class. This roughly lead to the code found below:
class Parent {
public:
virtual void func();
// Getter function
uint8_t getID() {
return classID;
}
// Set ID to a default value
const uint8_t classID = 0;
};
// One of many child classes
class A: public Parent {
public:
void func() {//do something}
const uint8_t classID = 1;
};
int main(){
Parent* childPointer = new A;
uint8_t currentID = childPointer -> getID();
}
However, running this led to currentID being equal to Parent.classID rather than A.classID.
Making the getID function virtual and definining it in each of the child classes made it work as intended, but this would lead to quite a bit of repeated code. I was wondering if there was a way to define the getter function once in the Parent class, and to make it return the correct value? Otherwise, is there a cleaner way to do it?
In C++ each class has it's own namespace. In your code you have a classID in the Parent namespace and a classID in the A namespace. So every instance of A actually has 2 classIDs. The getID() function only sees the classID in the Parent namespace though. This is why it only returns 0.
A better way would be to define constructors which will initialize the classID in Parent:
#include <cstdint>
class Parent {
public:
Parent(): classID(0){}; //Default Parent initializes with 0
Parent(uint8_t ID): classID(ID){}; //Constructor to be called by children
virtual void func(){};
// Getter function
uint8_t getID() {
return classID;
};
const uint8_t classID;
};
// One of many child classes
class A: public Parent {
public:
A(): Parent(1){}; //Every A calls Parent(uint8_t) constructor
void func() {};//do something
//const uint8_t classID = 1; //This is not needed anymore
};
int main(){
Parent* childPointer = new A;
uint8_t currentID = childPointer -> getID();
}