#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.
Related
#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
I have an abstract class, that has two variables. I want to instantiate those variables through the constructor.
Then I want to instantiate those variables from the child classes constructors, but it giving me a casting error?
#ifndef Employee_Interface_H
#define Employee_Interface_H
#include <iostream>
using namespace std;
class Employee {
private:
double salary = 0;
double sales = 0;
double bonus = 0;
public:
Employee(double empSalary, double empSales) {
salary = empSalary;
sales = empSales;
}
void virtual calculateBonus() = 0;
};
class Staff : public Employee {
public:
Staff(double empSalary, double empSales) {
Employee(empSalary,empSales);
}
void calculateBonus() {
//20% of salary
}
};
#endif
`
Instead of this:
Staff(double empSalary, double empSales) {
Employee(empSalary,empSales);
}
Use this instead:
Staff(double empSalary, double empSales) :
Employee(empSalary, empSales)
{
}
You have to put the base class constructor call in the derived class constructor's member-initialization-list - after the : marker, but before the constructor's body definition.
I'm experimenting with the decorator design pattern in c++. However, I was not able to implement it without an abstract super-class from which both the core and decorating classes inherit.
I don't understand why abstract super-class is needed.
My working decorator example:
#include <string>
#include <iostream>
using namespace std;
// abstract superclass
class Pizza
{
public:
virtual string GetDescription() = 0;
virtual int GetCost() = 0;
};
// base class that can be extended
class Margharita: public Pizza
{
private:
string description;
int cost;
public:
Margharita(string t, int c){description = t; cost = c;}
string GetDescription(){return(description);}
int GetCost(){return(cost);}
};
// decorator class that extends base class
class ExtraCheese: public Pizza
{
private:
Pizza* pizza;
public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}
string GetDescription() { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() { return(pizza->GetCost() + 20); }
};
int main()
{
// create decorated object
Pizza* pizza = new ExtraCheese(new Margharita("Margharita", 100));
cout << pizza->GetDescription() << '\n';
cout << pizza->GetCost() << '\n';
}
that gives the output: Margharita, Extra Cheese 120.
If I remove the abstract super-class, the decoration stops working:
#include <string>
#include <iostream>
using namespace std;
// base class that can be extended
class Pizza
{
private:
string description;
int cost;
public:
Pizza(){description = "Pizza"; cost = 100;};
string GetDescription(){return(description);}
int GetCost(){return(cost);}
};
// decorator class that extends base class
class ExtraCheese: public Pizza
{
private:
Pizza* pizza;
public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}
string GetDescription() { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() { return(pizza->GetCost() + 20); }
};
int main()
{
// create decorated object
Pizza* pizza = new ExtraCheese(new Pizza());
cout << pizza->GetDescription() << '\n';
cout << pizza->GetCost() << '\n';
}
In this case the output only shows the attributes of the core object (Pizza 100).
Why is this happening?
When you removed the abstract base class you made the function GetDescription and GetCost not virtual. As such they aren't dispatched dynamically. Which is why pizza->GetDescription() called the Pizza member function, it was a call resolved based on the static type of pizza only.
You don't need to have an abstract base to make it work again, only dynamic dispatch, so just add the virtual specifier
class Pizza
{
private:
string description;
int cost;
public:
Pizza(){description = "Pizza"; cost = 100;};
virtual string GetDescription(){return(description);}
virtual int GetCost(){return(cost);}
};
This will allow overriding in ExtraCheese, to be picked up by dynamic dispatch. You can also help the compiler catch such mistakes by employing the override specifier. Had you defined ExtraCheese like this:
class ExtraCheese: public Pizza
{
private:
Pizza* pizza;
public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}
string GetDescription() override { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() override { return(pizza->GetCost() + 20); }
};
A modern compiler would have complained you are trying to override a function that isn't declared virtual. The mistake would have been apparent.
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");
}
#include <boost/scoped_ptr.hpp>
class classA
{
protected:
struct StructB
{
int iAge;
double dPrice;
};
boost::scoped_ptr<StructB> m_scpStructB;
public:
classA(int age, double price)
: m_scpStructB(new StructB)
{
m_scpStructB->iAge = age;
m_scpStructB->dPrice = price;
}
/* DO NOT COMPILE <= second block
classA(int age, double price)
: m_scpStructB(new StructB),
m_scpStructB->iAge(age),
m_scpStructB->dPrice(price)
{}
*/
};
Question1> I have found that I cannot use the second block of code to initialize structure members pointed by a smart pointer. Is it a general c++ rule that we just cannot do it.
Please discard this question if the answer to the first question is "You cannot do it".
Question2> As far as I know, the order of assignment on initialization list is based on the order of member variables definition. Assume that you can initialize the member variables through smart pointer. How can you guarantee the order so that the smart point is initialized always first?
If you don't need StructB to be an aggregate/POD type, then just give it a constructor too:
#include <boost/scoped_ptr.hpp>
class classA
{
protected:
struct StructB
{
StructB(int age, double price) : iAge(age), dPrice(price) { }
int iAge;
double dPrice;
};
boost::scoped_ptr<StructB> m_scpStructB;
public:
classA(int age, double price) : m_scpStructB(new StructB(age, price)) { }
};
Otherwise you can just use a factory function, so that it remains a POD type:
#include <boost/scoped_ptr.hpp>
class classA
{
protected:
struct StructB
{
int iAge;
double dPrice;
static StructB* make(int age, double price)
{
StructB* ret = new StructB;
ret->iAge = age;
ret->dPrice = price;
return ret;
}
};
boost::scoped_ptr<StructB> m_scpStructB;
public:
classA(int age, double price) : m_scpStructB(StructB::make(age, price)) { }
};