No definition in cpp composition when I define in function - c++

#include <iostream>
using namespace std;
class Date{
private:
int day;
int month;
int year;
public:
Date(int dy,int mt,int yr){
day=dy;
month=mt;
year=yr;
}
void showDate(){
cout<<day<<"/"<<month<<"/"<<year<<endl;
}
};
class Human{
private:
string name;
Date birthDay;
public:
Human(string nm,Date bd):name(nm),birthDay(bd){};
showHumanInfo(){
cout<<"The person named : "<<name<<" was born : ";
birthDay.showDate();
}
};
int main()
{
Date birthday(1,2,1995);
Human h1("alek",birthday);
h1.showHumanInfo();
return 0;
}
This works, but why it doesn't work when I do the following?
#include <iostream>
using namespace std;
class Date{
private:
int day;
int month;
int year;
public:
Date(int dy,int mt,int yr){
day=dy;
month=mt;
year=yr;
}
void showDate(){
cout<<day<<"/"<<month<<"/"<<year<<endl;
}
};
class Human{
private:
string name;
Date birthDay;
public:
Human(string nm,Date bd){
name = nm;
birthDay = bd;
}
showHumanInfo(){
cout<<"The person named : "<<name<<" was born : ";
birthDay.showDate();
}
};
int main()
{
Date birthday(1,2,1995);
Human h1("alek",birthday);
h1.showHumanInfo();
return 0;
}
I have problem like that. Why can't I use date class in a human class?
When I change human public class like that
public:
human(){
// ...
}
It not working it thing is the same think but not adding date class in human class.

In the definition of a constructor, all member variables must be initialized before the body of the constructor is executed. Since Date doesn't have a default constructor, there is no way to initialize it
Human(string nm, Date bd)
{ // birthDay must be initialized before this point
// ...
birthDay = bd; // this is assignment, which is too late
}
The fix is to either give Date a default constructor, if that makes sense, or to initialize birthDay in a member initializer list, as you did in the first example code.

I think problems comes from "birthday = bd;"
It has been a while since the last time I coded in C++ but if I am not wrong, using constructor initialiser and using equal operator are not the same.
You should override "=" operator to use it with your object.
About his

Related

C++ - Unable to inherit from base class | Gives empty values

I guess I am doing something wrong here in the below code. I want to inherit the methods of class Person in class Employee.
#include<bits/stdc++.h>
using namespace std;
class Person{
private:
string name;
int age;
public:
Person(string name, int age){ //Base parameterized constructor
name = name;
age = age;
}
void getName(){
cout<<"Name: "<<name<<endl;
}
void getAge(){
cout<<"Age: "<<age<<endl;
}
};
class Employee: public Person{ //Default inheritance type is private
private:
int employeeID;
public:
Employee(string name, int age, int id) : Person(name, age){ //Derived parameterized constructor
employeeID = id;
}
void getEmployeeDetails(){
getName();
getAge();
cout<<"Employee ID: "<<employeeID<<endl;
}
};
int main(){
Employee* e = new Employee("John", 24, 14298);
e->getEmployeeDetails();
return 0;
}
I am getting the below output:
Name:
Age: 0
Employee ID: 14298
Please let me know what am I missing here. Any help would be appreciated!
The issue is not with inheritance, but with the fact that Person never initializes any of its fields.
This code:
Person(string name, int age){ //Base parameterized constructor
name = name;
age = age;
}
assigns local variable name to itself and same with age, because parameters shadow class member names. Member objects with the same name are never initialized.
Three solutions possible (listed in subjective order in which I prefer them):
Use member initializer list to initialize your members:
Person(string name, int age) : name{name}, age{age}
{
}
Use different names
Person(string providedName, int providedAge)
{
name = providedName;
age = providedAge;
}
Use this to disambiguate objects
Person(string name, int age){ //Base parameterized constructor
this->name = name;
this->age = age;
}
Nothing to do with inheritance, the code would have been wrong anyway.
This
Person(string name, int age){ //Base parameterized constructor
name = name;
age = age;
}
should be this
Person(string n, int a){
name = n;
age = a;
}
Because your constructor parameter declaration names are the same as your member variables, the member variables are hidden and you were just assigning the parameters to themselves.
A better way to write the same code is to use an initialiser list
Person(string name, int age) : name(name), age(age)
}
Initialiser lists have a couple of advantages, one of them is that there's no ambiguity, you can have the parameter names the same as the member variable names. The other (more important) is that in general, initialisation is more efficient than assignment.

Inheritence of C++11 class

#include <string>
#include <iostream>
using namespace std;
class Surgery
{
public:
Surgery();
int getPrice();
string getType();
protected:
int price;
string type;
};
Surgery::Surgery()
{
price = 0;
type = "";
}
int Surgery::getPrice()
{
return price;
}
string Surgery::getType()
{
return type;
}
class Neurosurgery :public Surgery
{
private:
string type = "Neurosurgery";
int price = 23000;
};
class Plastic :public Surgery
{
private:
string type = "Plastic";
int price = 15000;
};
class Trauma :public Surgery
{
private:
string type = "Trauma";
int price = 5000;
};
class Endocrine :public Surgery
{
private:
string type = "Endocrine";
int price = 20000;
};
class Ophthalmological :public Surgery
{
public:
Ophthalmological();
private:
string type;
int price;
};
Ophthalmological::Ophthalmological():Surgery()
{
type = "Ophthalmological";
price = 10000;
}
int main()
{
Ophthalmological var1;
cout << var1.getPrice() << endl;
return 0;
}
When i run this code i expected to see 10000
Instead i see 0
I made it really simple to avoid any mistake with const, singlone default constructors.
First Surgery constructor gets executed after Neurosurgery.
Neurosurgery constructor should overwrite values that default Surgery constructor made.
Am i using c++11 in wrong style
This is because you are declaring tow times the variable price and type and, and when you are invoking cout << var1.getPrice() << endl; it takes the variable of Surgery. You should do:
class Surgery
{
public:
Surgery();
int getPrice();
string getType();
protected:
int price;
string type;
};
class Ophthalmological :public Surgery
{
public:
Ophthalmological();
private:
//string type; //It has been declared into Survey
//int price; //It has been declared into Survey
};
I ran your code with this modification and return the value of the unique price variable.
This is caused by the fact that it is not virtual, and there are multiple variables with the same name. So you get value from the base class Surgery. The other classes also define the variables with the same name. I think the simplest solution is this: Keep the protected variables in the base class and remove those variables from the subclasses.

not able to implement my simple friend function C++

take a look at friend function i am trying to implement
#include <iostream>
#include <string>
using namespace std;
class Customer {
friend void displayInfo(Customer, City);
private:
int custNum;
int zipCode;
};
class City {
friend void displayInfo(Customer, City);
string cityName;
int zipCode;
};
void displayInfo(Customer cus, City city) {
cout << cus.custNum; //compiler error - Inaccessible
}
I understand it is inaccessible. However i have the friend function already defined in the class. So why it is not accessible? Thank you
While you are declaring displayInfo() function as a friend of City and Customer classes, the classes City and Customer given to displayInfo as parameters(i.e. in the declaration) are not defined yet.
If you simply add two lines to the top of your code, as shown here, it does compile.
class City;
class Customer;
Tested code. Only necessary to add class City;
#include <iostream>
#include <string>
using namespace std;
class City;
class Customer {
friend void displayInfo(Customer, City);
private:
int custNum;
int zipCode;
};
class City {
friend void displayInfo(Customer, City);
string cityName;
int zipCode;
};
void displayInfo(Customer cus, City city) {
cout << cus.custNum; //compiler error - Inaccessible
}

Inheritance and Multiple Constructor

Okay so I have this person class.
#ifndef PERSON_H
#define PERSON_H
#include<string>
using namespace std;
class Person
{
protected:
string name;
int age;
public:
Person();
Person(string newname, int newage);
void SetName(string n);
void SetAGe(int a);
string GetName();
int GetAge();
};
#endif
And the following person.cpp file.
#include "Person.h"
Person::Person(string newname, int newage){
name = newname;
age = newage;
}
And this Employee.h and .cpp file
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
#include<string>
#include "Person.h"
using namespace std;
class Employee : public Person
{
protected:
float payrate;
public:
//Member functions
Employee() : Person(){ payrate = 10; }; //Constructor
Employee(float newpay); //Constructor
void SetPayrate(float p);
float GetPayrate{ return p; }
#endif
Here's the cpp I had forgotten
#include "Employee.h"
Employee::Employee(float pay) : Person()
{
payrate = pay;
}
And this is supposed to be able to use this line of code
Employee b("Jane", 21, 12.38);
To create an employee with the name Jane, age 21, and payrate of 12.38, but it says that there is no method of the matching arguments. Am I missing something basic? Thanks.
Your Employee class has two explicitly declared constructors:
Employee() : Person(){ payrate = 10; }; //Constructor
Employee(float newpay); //Constructor
The compiler gives you a copy constructor. Given these, you can construct an Employee using one of the three constructors only.
Employee e1; // OK. Uses the first constructor.
Employee e2(2.4f); // OK. Uses the second constructor.
Employee e3(e2); // OK. Uses the copy constructor
Employee e4 = e2; // OK. Uses the copy constructor
Any other way of constructing an Employee is not allowed. If you want to construct an Employee using
Employee e5("Jane", 21, 21.38);
you have declare a constructor that can accept those as arguments. E.g.
Employee(std::string const& name, int age, float payrate);
Constructors are not inherited, and the compiler won't create new constructors like this for you.
You didn't write a constructor Employee(string, int, float), so you can't call it.
If you add one, then you can:
// in the Employee class
Employee(string newname, int newage, float newpayrate)
: Person(newname, newage)
{
payrate = newpayrate;
}
You can, of course, put it all on one line if you want.
You could also put the definition in Employee.cpp, if you want. (Either way works.)

Can we call member function only in member initialization list in c++?

I want provide a class with a member function that will initialize the all member of class separately.
e.g.
#include <iostream>
using namespace std;
int x = 10;
class my{
public:
my():init{}
int &i;
void init()
{
i = x;
}
};
int main()
{
my m;
return 0;
}
I know if I can use "class my : i(init())" will work, but I have some special purpose to intialize like above.
However in above example, I'm getting following error:
class ‘my’ does not have any field named ‘initMy’.
How to resolve this?
If you are trying to write a constructor for class my, then it must be named with the class name. The following will work assuming that initMy is the name of another class that you are trying to subclass.
class my : initMy
{
public:
int i;
my() {
i = 10;
}
};
You might try to pre-initialize all the fields, then calling the initializing function inside the constructor:
class my {
public:
int i;
void initMy() {
i = 10;
}
my() : i(0) { initMy(); };
};
You could also (in C++11) define a bizarre signature for a private constructor, and delegate a constructor to it
class my {
private:
void initMy () { i=10; };
enum privateen {privatev};
my(enum privateen) : i(0) { initMy(); };
public:
my() : my(privatev) {};
int i;
};
Actually, I believe that your initialization should be in a constructor, not in some other function.
Few things to clarify here.
Member initialization list is for initialize members (mostly same purpose of the constructor).In initialize list nothing to do with member functions. in this example age(newAge) is not a function. It is initializing age variable.
class Man{
private:
int age;
string name;
public:
Man(int newAge):age(newAge),name("Jhon"){}
};`
You can use constructor to initialize the members of the class.
class Man{
private:
int age;
string name;
public:
Man(int newAge)
{
age = newAge;
name = "Jhone";
}
};
Alternatively you can use a init method to do initialization, if you have some issue to use constructor.
class Man{
private:
int age;
string name;
public:
Man(){}
init(int newAge, string newName)
{
age = newAge;
name = newName;
}
};
If you need to set the value of only one member in a class, you have to use a setter method
class Man{
private:
int age;
string name;
public:
Man(){}
setAge(newAge)
{
age = newAge;
}
setName(newName)
{
name = newNAme
}
};
edit:
class Man{
private:
int age;
string name;
public:
Man(initAge, initName)
{
setValues(initAge, initName);
}
setValues(newAge, newName)
{
age = newAge;
name = newName;
}
};
int main()
{
Man goodMan(34,"Jhon");
goodMan.setValues(45,"Kevin");
}