Fields of Parent Class not recognized - c++

I've benn having a problem for a while, when I'm trying to inherit from a pure virtual class, when I make the constructor for the "son" classes I receive this error:
../src/Course.cpp:54:77: error: class ‘ElectiveCourse’ does not have any field named ‘_dptr’
And this happens for all of the Course Protected fields.
This is the structure:
Course.h:
class Course{
public:
virtual void reg(Student * s) = 0;
..
protected:
...
string _dptr;
...
};
and then:
class ElectiveCourse : public Course{
...
}
Course.cpp:
ElectiveCourse::ElectiveCourse(
string name,
int semester,
double minGrade
)
: _dptr("CS"), _name(name), _semester(semester), _minGrade(minGrade) {
}
Like the ElectiveCourse, I have two other classes that inherit from the Course class, and I'm getting the same error in all of them.
[EDIT] This only happens in the Constructor of them.
There is NO constructor in the Course class hence it is pure virtual.
In the other hand, I also have two classe: Student, and CSStudent : Student, where Student is also pure virtual and CSStudent inherit Student, and in this case there are no errors. I did the same exact thing in both of them.
What seems to be the problem?
I'm sorry for my grammar errors.
[EDIT]
added the Course.cpp part where I'm getting the error.
Thanks!

You cannot initialize member variables of one class in another class. If you want to initialize the member variables of Course in a constructor, you have to add a constructor to Course. You can make that constructor protected if you like.
The alternative (probably better) would be to change your design to make Course an interface.

You can't initialize the fields of your parent class in the subclass constructor. The reason for that is that the construction order includes the construction of base class before you can actually address its inner fields. And construction of the base requires construction of its inner fields. That said, to achieve what you need, you should create a constructor in your base class that accepts all of your parameters (name, semester etc.) and invoke this constructor from your subclass constructor:
Course::Course(string name,
int semester,
double minGrade):
_dptr("CS"),
_name(name),
_semester(semester),
_minGrade(minGrade){}
ElectiveCourse::ElectiveCourse(string name,
int semester,
double minGrade):
Course(name, semester, minGrade){}

Related

Does it make sense to have a class without constructor?

I am wondering whether it makes sense to have a class without constructor if the derived classes have one. If not, is there a way of doing what I want differently?
My case is the following:
I want the users to only use the derived classes, but those have data members and methods in common.
EDIT: as default constructors exist for classes, it means that the user can always create an instance of Instrument directly, then how can I do what I want?
class instrument{
public:
double get_price();
std::string get_udl();
private:
double m_price;
std::string m_udl;
};
class stock : public instrument{
public:
double get_dividend();
private:
double m_dividend;
};
class option : public instrument{
public:
double get_strike();
private:
double m_strike;
};
I want the users to only use the derived classes, but those have data members and methods in common
Have your default (or any other) c'tor, but declare it with protected access. Now only derived classes may invoke it. Effectively making it usable only when inherited.
class instrument{
public:
double get_price();
std::string get_udl();
protected:
instrument() = default;
private:
double m_price;
std::string m_udl;
};
This also avoids the overhead associated with making a class abstract. If you don't need polymorphism, you shouldn't use it just to make a class usable only as a base class.
Have thought of Abstract class ?
An abstract class is a class that is declared abstract—it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed.
Isn't this what you are looking for ?
When there's no default constructor defined, the compiler will automatically generate one for you, doing nothing for members of basic types and calls the default constructor for members of struct/class types.
So the conclusion is, it makes no sense to have a class without any constructor because whenever you define an instance of that class you have to call at least one (more may be called with deligate construction).
Yes! Definitely it make sense. Because when user create the instance of derived class, first of all parent class's constructor will be called from within the derived class constructor. Even without you explicitly call it. And parent class's default constructor will be called even if you didn't create one. By default
public constructor with no parameter is present in every class
if it has no overridden constructor.
And yes all the public members of parent class will be present in derived class after creating derived class instance.

Using default constructors in C++

Hi all I am in Intro to Programming and am a little unsure about member initialization and default constructors. We are learning the basics of classes and structures but we haven't even gotten to constructor methods or inheritance yet, so I'm a little ahead of the class. I surfed the web and I couldn't find an exact answer to my question so I figured I would ask here:
class ProductionWorker : public Employee
{
private:
int shiftNum;
double hourlyPay;
public:
//constructor for ProductionWorker
ProductionWorker(int newShiftNum, double newHourlyPay) : Employee(getEmpName(), getEmpNum())
{
shiftNum=newShiftNum;
hourlyPay=newHourlyPay;
}
In this snippet the first problem that I ran into was I was getting an error that there was no default constructor for the class Employee and after some research I found out that if a class is inheriting another class, the inherited class needs to have a default constructor. I read a little more into member initialization and from my understanding, I can do away with the need for a default constructor of an inherited class if I just have the ProductionWorker constructor initialize the Employee constructor.
Is this correct?
The arguments that are passed into the Employee constructor are "getters" because I can't directly pass in the variables held in the Employee class because they are private, would this cause unforeseen problems?
Before you create a class, you cannot access its members. So Employee( getEmpName(), getEmpNum() ) makes no sense. You are supposed to pass those values into the constructor, and then later if you need them, call the accessors.
public ProductionWorker( string name, int num, int shiftNum, double pay ) :
Employee( name, num )
{
this->shiftNum = shiftNum;
this->hourlyPay = pay;
}
Inheritance is a is a relationship. When you create a ProductionWorker you are also creating a Employee. Since Employee only has a constructor that takes a name and number (I assume), those are usually passed into ProductionWorker so it can create the Employee correctly. As Noted below, there are alternatives, but this seems like the logical way in this scenario.
Base class do not need to have a default constructor. If they do not have a default constructor, each constructor of a derived class needs to explicit call one of the base class constructors from its member initializer list. However, you shouldn't attempt to use any member functions because the object isn't constructed, yet. You basically want to use the constructor arguments of the derived class to determine which values you want to pass to the base class.
In your specific example it looks as if the Employee base class wants to get a name and an employee number. You might want to pass them to your derived class in addition to the information need only by the derived object.
You understend it correctly I think but you've missused a notion.
Arguments of Employee class constructor can be it's setters, because they might allow you to set the private properties of base class.
A getter would allow you to get (no surprise) the value of private field.
By the way, constructor of inheriting class will always call the base class' constructors. Of course if the base class have constructor that accepts no arguments then there is no need to call it explicitly in inheriting class.
Imagine that you have classes:
class ColorCircle : public Circle{
string color;
ColorCircle (string c)
{
this.color = c;
}
}
and
class Circle {
double diameter;
Circle (double d)
{
this diameter = d;
}
}
If you want to create a ColorCircle you have to provide also the information about it's diameter but the constructor of ColorCircle does not have any place for this. Thats why constructor of ColorCircle should look like this:
ColorCircle (string c, double d) : Circle (d)
{
this.color = c;
}
And when you create a ColorCircle you just do:
new ColorCircle("red", 2.5);
The program takes care about passing the diameter value 2.5 to the proper base class constructor.

Why does a purely virtual/abstract class require a constructor, in particular for protected const member variables?

I have a purely virtual class defined as such:
class BaseClass {
protected:
const int var;
public:
void somefun() = 0; // what I mean by a purely virtual class
// stuff...
};
If I don't add a constructor defined as such:
BaseClass(const int & VAR) : var(VAR) {};
that I would have to subsequently use in ever derived class, my derived class can't initialize the const variable var to whichever value it wants to. Now I actually understand what's going on here. Before constructing a derived class, a constructor of the base class is called, at which point const member variables must be initialized. My question is not a "how do I make my code work" kind of question, that's already been done. My question is about why the compiler thinks it's necessary. For a purely virtual class, shouldn't I be allowed to write something like:
class DerivedClass : BaseClass {
public:
DerivedClass() : var(SOME_VALUE) {};
}
If the compiler knows that a call to a BaseClass constructor will necessarily be followed by a call to some derived class constructror (since an object of abstract type can never be instantiated) shouldn't it give us a bit more leeway?
Is this all a consequence of how C++ chooses to get around the Diamond problem? Even if that was the case, shouldn't the compiler at least somehow allow for the possibility that const member variable of purely virtual functions will be defined in derived classes? Is that too complicated or does that mess with the C++ solution to the Diamond problem?
Thanks for the help everyone.
It's not "purely virtual" (whatever you mean by that) - it contains a data member.
Class members can only be initialised by the initialiser list of a constructor of that class, not of a derived class. That's how object initialisation is specified: all members that are initialised, are initialised before the constructor body begins.
Constant objects must be initialised, since they can't be assigned a value later.
Therefore, a class with a constant data member must initialise it in each constructor.
For a purely virtual class, shouldn't I be allowed to write something
like
No, but you can(and in this case should) write something like this:
class DerivedClass : BaseClass {
public:
DerivedClass() : BaseClass(SOME_VALUE) {};
};
The construction of an object occurs in a specific order. The base class must be fully constructed before the constructor of a derived class is run, so that the derived constructor is working with a fully formed and valid base object. If the initialization of base member variables were put off until the construction of the derived class, this invariant would be broken.

How can a child class call the constructor of the parent class that initializes member variables differently? [C++]

How can I compute the value of a child class's member variable in it's constructor, and then pass on to the parent's constructor??
The motivation is that, if there's a lot of calculation in the parent class default constructor, then I don't want to have to do those calculation and only have them replaced by those computed by child class right after.
For example:
Car.h
class Car
{
public:
Car();
Car(double Price) ;
...
private:
double price;
double DetermineMarketPrice();
};
Car.cpp
Car::Car()
{
//some other long computation
price = DetermineMarketPrice();
}
Car::Car(double Price)
{
price = Price;
}
...
Porche.h
class Porche : public Car
{
public:
Porche();
...
private:
double price;
double discount;
double fee;
double DetermineMarketPrice();
double RetrieveFee();
double CheckDiscount();
...
};
Porche.cpp
Porche::Porche():Car(price)
{
discount = CheckDiscount();
fee = = RetrieveFee();
price = DetermineMarketPrice() * (1-discount) + fee;
}
In this case, the price of a Porche isn't known yet. It has to be calculated in the constructor. If I call the parent's constructor like this, seems like it would only pass the not-yet-initialized price.
What would be a good way to pass some value of member variables that can only be known at the end of the Child class initialization???
You can't do that, the base class constructors are executed first in the initialisation order, before data members are initialised and before the derived class constructor's body is executed. If these are costly calculations, the best thing to do may be moving them out of the constructor.
EDIT: There's technically a way to work around this problem, by creating a second constructor, or having a default constructor with a default parameter value, which can be used to stop the calculations in the base class, like so:
struct SkipCalculatePrice {};
class Car {
public:
Car();
protected:
Car(SkipCalculatePrice);
};
class Ferrari: public Car {
public:
Ferrari(): Car(SkipCaluclatePrice()) [...]
[...]
However, I personally would not recommend this as a good design practice. It is understood that one would want to avoid delayed initialization as an anti-pattern, however, for costly calculations, properly done lazy initailization might be the right answer:
class Car {
virtual double calculatePrice();
bool priceCalculated;
double price;
public:
double getPrice() {
if(!priceCaluclated) {
price = calculatePrice();
}
return price;
}
}
class Ferrari: public Car {
double calculatePrice();
};
A lot depends on the actual situation, but one frequent solution is to
offload all of the calculations into a static member, so you can write:
Porsche::Porsche()
: Car( calclulatePrice() )
{
// ...
}
This won't work if (as your example suggests) you first have to
calculate other member variables, before setting the variable in the
base class. For cases like the one you present, the simplest solution
is just to initialize the base class with 0, and then set the actual
value later.
More generally, I have to wonder about your design. It can't be right
that both the base class and the derived class have a member price.
In the most frequent use of inheritance, the base class will be
abstract, with no data members. But even when this is not the case, the
data members of the base class are not duplicated in the derived
classes: if the derived classes can set or change them in an arbitrary
way, they may be protected; otherwise, they are in the base class, and
only manipulated by functions in the base class (which may be called
from the derived class).
Just move the calculation code out of the constructor to a utility function such as CalculatePrice( ). Construct the object and then call this function.
Use an virtual method in the constructor of the parent to determine the price. Redefine this method in each child class.

When I derive a class in C++, does it create an object of base class and store it as my member variable in derived class?

Say i create a derived class as below,
class CHIProjectData : public QObject
{
CHIProjectData(QMap<QString,QString> aProjectData,
CHIMetaData* apMetaData = 0,
QObject* parent = 0);
private:
QMap<QString,QString> m_strProjectData;
CHIAkmMetaData* m_pMetaData;
};
and i implement like,
CHIProjectData::CHIProjectData(QMap<QString,QString> aProjectData,
CHIMetaData* apMetaData,
QObject* aParent)
:m_strProjectData(aProjectData),
m_pMetaData(apMetaData),
QObject(aParent)
{
}
i know i initiate the member variables m_strProjectData, m_pMetaData in the constructor. but what does the last part "QObject(aParent)" do? does it create an object of base class and consider that as a member variable?
QObject(aParent) calls QObject's constructor with the aParent parameter. QObject is not a member variable in this case. It may seem like a subtle point, but its an important one because the way you access the properties and methods of a subobject requires different syntax than as for a member variable.
Here's an analogy to try to understand the difference between a subobject and a member variable.
In the movie "Batman: The Dark Night" there is a scene where Batman is pursuing the bad guy in his car. But the car becomes damaged and unusable, and he has to escape. At that point Batman pushes a button and part of the car detatches from the rest, becoming a motorcycle. This is kind of like a subobject. The car is a motorcycle.
Now consider the case of an RV towing a smaller vehicle, the likes of which are frequently seen on the highways of America. In this case, the RV has a vehicle. The vehicle is a member variable of the RV.
Essentially, that is what is happening under the hood. The base class parts of your object, like its data members, are called subobjects.
The notion of initializing a base as in QObject(aParent) is similar to initializing a member, but bases are always initialized first. Therefore, it would be clearer to list QObject before the members, so the list of initializers is in chronological order.
The order of initialization always follows the order the bases are named after class and the order the members are declared, no matter how the initializer sequence is written.
A class instance that is a base of a derived class is sometimes called a "base class subobject", so in some sense a base class is a distinct 'part' of your derived class.
In your constructor's initializer list, the QObject(aParent) is choosing how the base class is constructed. In this case a single parameter constructor is being used. If the base class were omitted from the initializer list of your derived class' constructor its default constructor would be used.
It's not strictly a member variable, although like a member variable it's a constituent part of your derived class along with any other base class subobjects and other members.
Not quite. It tells the base class's constructor what to do. Imagine this class:
class A
{
public:
A(int val)
: value(val)
{
}
protected:
int value;
};
To construct A, you have to pass an int. This is always true, even if you derive from it.
Say you are class B, which derives from A. You are an A, but you still have to tell the A part of your class how to construct itself:
class B : public A
{
public:
B()
: A(5)
{
}
int GetValue()
{
return value;
}
};
The members of A become your members, though, because you are an A.
In machine memory, the scenario is kind of how you described, but only in simple cases. It becomes more complicated with virtual functions, multiple inheritance, and virtual inheritance. If you stick to the is-a and has-a relationships, then you may avoid some headaches :)