Constructor for a class within a class - c++

I have 2 classes, Date and Employee.
//Date
class Date
{
private:
int dd;
int mm;
int yy;
public:
Date (int, int, int);
void setDate (int, int, int);
int getDD();
int getMM();
int getYY();
};
//Employee
class Employee
{
private:
int ID;
string qualification;
double salary;
Date DOB;
Date dateJoined;
public:
Employee();
void setEmployee (int, string, double, Date, Date);
Date getDOB();
Date getDateJoined();
string getQualification();
void displayEmployee();
};
This is my constructor for Employee class.
Employee::Employee()
{
ID = 0;
qualification =" " ;
salary=0.0;
Date DOB();
Date dateJoined();
}
I got error C2512: 'Date' : no appropriate default constructor available.
How do I initialize DOB and dateJoined inside the Employee class?

The issue is that before the Employee constructor body is entered, all of the data members are constructed. In this instance, DOB and dateJoined need to be default-initialized, but there is no default constructor for your Date class. Your two main options are to add a default constructor for Date, or to initialize those members in the Employee constructor initializer list.
Option 1:
class Date
{
Date (); //define this somewhere
};
Option 2:
Employee::Employee() :
ID(0),
qualification(" "),
salary(0.0),
DOB(/*some data, maybe taken in as constructor args*/),
dateJoined(/*ditto*/)
{ }

Try this modification. You need a constructor Date():
class Date
{
private:
int dd;
int mm;
int yy;
public:
Date () {return;}
Date (int, int, int);
void setDate (int, int, int);
int getDD();
int getMM();
int getYY();
};
Another solution is:
Employee::Employee():
DOB(0,0,0),
dateJoined(0,0,0)
{
ID = 0;
qualification =" " ;
salary=0.0;
}

Related

no default constructor exists for class in C++ [duplicate]

This question already has answers here:
No default constructor?
(2 answers)
no default constructor exists for class
(5 answers)
Closed 1 year ago.
I have created a constructor, but why there is still have an error "no default constructor exists for class"?
I have searched for the answer to the question, but I am still not clear about this error. Can someone help me?
pragma once
#include<string>
using namespace std;
class Date
{
private:
int month;
int day;
int year;
public:
Date(int newmonth, int newday, int newyear)
{
month = newmonth;
day = newday;
year = newyear;
}
};
class Student
{
private:
string name;
Date birthDay;
int score;
public:
Student(string newname, Date newbirthDay, int score)
{
}
};
In Student, you need to initialize the Date birthDay variable as part of the constructor's initialization list, otherwise it will attempt to initialize it with the default constructor, which does not exist. Example:
Student(string newname, Date newbirthDay, int score) : name(newname), birthDay(newbirthDay), score(score) {
}
In general, you should be using the initialization list (same for your Date class).
On an unrelated note, you should consider passing objects in by const &, i.e.:
Student(const string &newname, const Date &newbirthDay, int score) : name(newname), birthDay(newbirthDay), score(score) {
}
A default constructor needs an empty parameter list, so in your case it'd be Date() or Student()

How to set an attribute of a base class in a constructor of a sub class c++

I have the following constructor in a class Student that is a subclass of a base class Person:
namespace Uni
{
Uni::Student::Student(string majorCourse, int enrollNumber , string name, int age, bool isStudying)
: Uni::Person::Person(std::__1::string name, int age, bool isStudying), majorCourse_(majorCourse), enrollNumber_(enrollNumber)
{
cout << "[Temp] Student Default Constructor" << endl;
}
...
}
I would like to set the attributes name_, age_ and isStudying_ (which are attributes of the Person class) to the values of name, age, and isStudying, but I get an error on this statement:
Uni::Person::Person(std::__1::string name, int age, bool isStudying)
type name is not allowed
How can I fix this?
You should just be forwarding the arguments along to the base class, so lose the typenames
Uni::Student::Student(string majorCourse, int enrollNumber , string name, int age, bool isStudying)
: Uni::Person::Person(name, age, isStudying),
majorCourse_(majorCourse),
enrollNumber_(enrollNumber)
{ }

Call constructor with different argument types from another constructor in C++17

I have a class called Date:
class Date {
public:
explicit Date(const int day = 1, const int month = 1, const int year = 0) {
this->Construct(day, month, year);
}
explicit Date(const string &date_as_string) {
int day, month, year;
// parsing the string date_as_string
this->Construct(day, month, year);
}
private:
void Construct(const int day, const int month, const int year) {
// constructing the Date object
}
};
Is there a way to call Date(int, int, int) directly from Date(string&), thus avoiding writing a separate function?
UPD:
Some clarification. My class should look like:
class Date {
public:
explicit Date(const int day = 1, const int month = 1, const int year = 0) {
// constructing the Date object
}
explicit Date(const string &date_as_string) {
int day, month, year;
// parsing the string date_as_string
// call Date(day, month, year) to construct the Date object
}
// any other functions
private:
// private fields
};
And the following code should compile:
Date date("some_string_containing_date");
Date date(1, 1, 0);
Yes, you can define one constructor in terms of another. No, I don't think you can do it without some additional function.
A constructor which invokes another constructor of the same class is called a "delegating constructor", and uses the same sort of syntax as a member initializer list, but using the class's own name instead of its base classes and members:
ClassName::ClassName(SomeParam1 p1, SomeParam2 p2)
: ClassName(arg_expr1, arg_expr2, arg_expr3)
{ /* any other logic after the target constructor finishes */ }
But this case is a bit tricky because of the need for the intermediate object date_as_struct. Or with the updated question, just the need to do some parsing before entering another constructor. I'd solve this one by making an additional private constructor which takes the Date_as_struct:
class Date {
public:
explicit Date(int day = 1, int month = 1, int year = 0);
explicit Date(const string &date_as_string);
/* ... */
private:
struct Date_as_struct {
int day;
int month;
int year;
};
explicit Date(const Date_as_struct&);
static Date_as_struct ParseStringContainingDate(const std::string&);
};
Date_as_struct and ParseStringContainingDate are declared here as private, since it sounds like nothing else will really use them.
Then for the string constructor, you just have
Date::Date(const std::string& date_as_string)
: Date(ParseStringContainingDate(date_as_string))
{}
The Date(const Date_as_struct&) constructor can very easily delegate to Date(int, int, int) or vice versa, whichever is more natural for the actual member initialization.

C++ Inheritance: Calling constructor w/ args

I'm trying to invoke my parent class's constructor that has arguments, in my child class's constructor with arguments, but I get a compiler error "expected primary expression before ...".
This is what I have:
class Ship {
private:
string shipName;
int yearBuilt;
public:
Ship();
Ship(string name, int year);
};
class CruiseShip: public Ship {
private:
int maxPeople;
public:
CruiseShip()
: Ship() {
maxPeople = 100;
}
CruiseShip(int m)
: Ship(string name, int year) {
maxPeople = m;
}
};
Ship::Ship() {
shipName = "Generic";
yearBuilt = 1900;
}
Ship::Ship(string name, int year) {
shipName = name;
yearBuilt = year;
}
And this is the specific piece of code I'm having trouble with:
CruiseShip(int m)
: Ship(string name, int year) {
maxPeople = m;
}
My goal is to be able to create an object, CruiseShip c1 with 3 arguments that set the name,year, & max people.
I've been reading online and it tells me that this should be ok, but I'm obviously doing something wrong. I'd appreciate any input, thanks!
You need to pass parameters to parent class constructor like this:
CruiseShip(int m, string name, int year): Ship(name, year), maxPeople(m) {}
Better, you should set maxPeople to m in the initializer list.

No matching function for call to [class]

So, I have some classes that I was defining, and it gave me errors for this:
#include <iostream>
using namespace std;;
//void makepayment(int amount, string name, Date date);
//void listpayments();
class Date;
class Date {
public:
int month;
int day;
int year;
Date(int month, int day, int year) {
this->month = month;
this->day = day;
this->year = year;
}
};
class Payment {
public:
int amount;
string name;
Date date;
Payment(int amount, string name, Date date) {
this->amount = amount;
this->name = name;
this->date = date;
}
};
int main() {
cout <<
"|~~~~~~~~~~~~~~~~~~~~~~~~| \n" <<
"| WELCOME TO THE | \n" <<
"| WESSLES BANK | \n" <<
"| MANAGEMENT SYSTEM! | \n" <<
"|~~~~~~~~~~~~~~~~~~~~~~~~| \n";
for(;;) {
}
return 0;
}
The error was:
foo.cpp: In constructor ‘Payment::Payment(int, std::string, Date)’:
foo.cpp:26:49: error: no matching function for call to ‘Date::Date()’
foo.cpp:26:49: note: candidates are:
foo.cpp:14:5: note: Date::Date(int, int, int)
foo.cpp:14:5: note: candidate expects 3 arguments, 0 provided
foo.cpp:9:7: note: Date::Date(const Date&)
foo.cpp:9:7: note: candidate expects 1 argument, 0 provided
I have no idea what is wrong! What does 'no matching function for call' mean?
Sorry if this is a noobie question... I just started c++.
This is because you've tried to copy an object and there is no default constructor supplied.
this->date = date;
What you should be doing, is initializing everything in the initializer list. There is also no reason you shouldn't be passing some of these arguments by reference.
Payment(int amount, const string& name, const Date& date)
: amount(amount)
, name(name)
, date(date)
{}
Same goes for your Date class. This will use the compiler generated copy constructor. Be aware that if your class contains more then POD types, you might want to implement your own copy constructor.
Because you have
Date date;
in your Payment class, you must have a Date constructor that takes no arguments, i.e. Date::Date(), which you do not have specified.
The Payment class has a Date child. The Payment constructor is first trying to instantiate the Date child with the default constructor, then later assigning a new value to this child. The problem is that the Date child does not have a default constructor Date::Date(). Either give the Date class a default constructor or change the Payment constructor syntax as follows:
Payment::Payment(int amount_, string name_, Date date_) : amount(amount_),
name(name_), date(date_)
{
}
Edit: Aesthete beat me to it