This question already has answers here:
What are the rules for calling the base class constructor?
(10 answers)
Closed 7 years ago.
Hey guys. I dont know how i suppose to do about setting values to derived classes ctor. And here is my code. I remember something like that build in my class. But i know that we can write something like that build ( xxx():yyy(){,,,};).
Check the main's second object.
#include <iostream>
using namespace std;
class vehicle
{
protected:
string brand;
int wheelNumber;
double maxSpeed=0;
public:
vehicle(){cout<<"default ctor for vehicle"<<endl;}
vehicle(string br1, int wn1, double ms1)
{brand=br1; wheelNumber=wn1; maxSpeed=ms1;}
void setbrand(string br){brand=br;}
string getbrand(string br){return brand;}
void setWN(int wn){wheelNumber=wn;}
int getWN(int wn){return wheelNumber;}
void setMaxS(double ms){maxSpeed=ms;}
double getMaxS(double ms){return maxSpeed;}
~vehicle(){cout<<"dtor for vehicle."<<endl;}
};
class car: public vehicle
{
private:
int numberOfDoors;
string fuelType;
public:
car(){cout<<"default ctor for car"<<endl;}
car(int nOD,string fT){numberOfDoors=nOD; fuelType=fT;}
void setnOD(int nOD){numberOfDoors=nOD;}
int getnOD(int nOD){return numberOfDoors;}
void setfT(string fT){fuelType=fT;}
string getfT(string fT){return fuelType;}
void printFeatures()
{
cout<<endl;
cout<<"brand:"<<brand<<endl;
cout<<"wheelNumber:"<<wheelNumber<<endl;
cout<<"MaxSpeed:"<<maxSpeed<<endl;
cout<<"NumberOfDoors:"<<numberOfDoors<<endl;
cout<<"FuelType:"<<fuelType<<endl<<endl;
}
~car(){cout<<"dtor for car."<<endl;}
};
int main()
{
car *cc;
cc= new car;
cc->setbrand("bmw");
cc->setfT("diesel");
cc->setMaxS(333.25);
cc->setWN(4);
cc->setnOD(6);
cc->printFeatures();
delete cc;
car *xx;
xx= new car;
car(5,"gasoline"):vehicle("mercedes",4,489.12);//Part that i cant figure it out.
xx->printFeatures();
delete xx;
}
The ctor(...):base(...){} syntax is used when defining the derived class constructor, not when instantiating an object. So change the constructor to car to this:
car(int nOD,string fT, string br1, int wn1, double ms1): vehicle(br1, wn1, ms1) {
numberOfDoors=nOD; fuelType=fT;
}
And instantiate your car object like this:
xx= new car(5,"gasoline", "mercedes",4,489.12);
Even better, take advantage of C++'s member-initialization syntax to define your constructors:
vehicle(string br1, int wn1, double ms1)
:brand(br1), wheelNumber(wn1), maxSpeed(ms1)
{}
// ...
car(int nOD,string fT, string br1, int wn1, double ms1)
: vehicle(br1,wn1, ms1), numberOfDoors(nOD), fuelType(fT)
{}
You need to code this into the constructor to get this to work. When you derive from a class the constructor of that derived class needs to take in the parameters for the base constructor and its own construction.
class Base
{
int foo;
public:
Base(int f) : foo(f) {};
};
class Derived : public Base
{
int bar;
public:
Derivced(int f, int b) : Base(f), bar(b) {}
^^^^^^^ ^^^^^^^^^
construct the base part constrcut the derived part
};
So for you example the constructor for car would become:
car(string br1, int wn1, double ms1, int nOD,string fT) : vehicle(br1, wn1, ms1),
numberOfDoors(nOD),
fuelType(fT) {}
Since you are allocating instance of class car which is derived class so it is calling both the ctors. First it will call the ctor of class 'vehicle' and then 'car'. [Read the order of calling ctor in case inheritance]
Related
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.
This question already has answers here:
Member variable needs parameters for constructor
(2 answers)
Closed 3 years ago.
I'm working with a cpp and .h file for every class, and I'm quite confused about how to use a member of another class which has a constructor with parameters.
MyClass.h:
#include "anotherClass.h"
class myClass
{
private:
int timeN;
anotherClass Object; //Following timeN example, it would be declared like so
public:
myClass(int timeN);
~myClass();
};
MyClass.cpp:
#include "myClass.h"
myClass::myClass(int timeN) {
this->timeN = timeN;
//how to create anotherClass object where waitInt is e.g. 500?
}
myClass::~myClass() {}
anotherClass.h:
class anotherClass;
{
private:
int waitInt;
public:
anotherClass(int waitInt);
~anotherClass();
};
anotherClass.cpp:
#include "anotherClass.h"
anotherClass::anotherClass(int waitInt)
{
this->waitInt = waitInt;
}
anotherClass::~anotherClass(){}
Edit: I can't use initialization lists, I am working on C++98. Therefore it hopefully isn't a duplicate, as all answers for linked post require initialization lists and therefore do not answer my question.
#include "myClass.h"
myClass::myClass(int argsTimeN) : timeN(argTimeN), Object(500) {
}
This is the correct way to initialize class member in C++. Using the = operator will make a copy of your object (unless you overloaded the operator).
Any class attributes not initialize that way, will be initialized using the default constructor if it exists
You can also use C++11 feature:
class myClass
{
private:
//private:
int timeN;
anotherClass Object{ 500 };
public:
myClass(int _timeN) : timeN(_timeN) { }
~myClass() = default;
};
if Object does not depend on any constructor parameter.
There are multiple ways to handle this case, depending upon your requirement when developing for more features.
Use a pointer for anotherClass inside MyClass
pointers
This way you create a pointer in the header and create an object while you are in the constructor and pass the desired value. You have to remember to delete the pointer in the constructor.
#include "anotherClass.h"
class myClass
{
private:
int timeN;
public:
myClass(int timeN);
anotherClass * m_pAnotherClass = nullptr; /* pointer to another class*/
~myClass();
};
#include "myClass.h"
myClass::myClass(int timeN) {
this->timeN = timeN;
//how to create anotherClass object where waitInt is e.g. 500?
m_pAnotherClass = new anotherClass(500);
}
myClass::~myClass() {
if(m_pAnotherClass == nullptr)
delete m_pAnotherClass;
}
2 Create the object in header and pass the waitInt via a setter function.
This way you can have an object created for anotherClass first and then set the int value in the constructor on myClass. The anotherClass object gets deleted when myClass object is delete.
#include "anotherClass.h"
class myClass
{
private:
int timeN;
anotherClass Object; //Following timeN example, it would be declared like so
public:
myClass(int timeN);
~myClass();
};
#include "myClass.h"
myClass::myClass(int timeN) {
this->timeN = timeN;
//how to create anotherClass object where waitInt is e.g. 500?
/* call setWaitInt mehtod and pass the value you want */
Object.setWaitInt(500);
}
myClass::~myClass() {
}
{
private:
int waitInt=0;
public:
anotherClass();
setWaitInt(int waitInt);
~anotherClass();
};
#include "anotherClass.h"
anotherClass::anotherClass()
{
}
anotherClass::setWaitInt(int waitInt)
{
this->waitInt = waitInt;
}
anotherClass::~anotherClass(){}
This question already has answers here:
no default constructor exists for class x (inheritance) C++
(2 answers)
Closed 8 years ago.
I seem to be having a problem with Inheritance. Whenever I try to override a function in my Character.cpp file I get an error stating:'No default constructor exists for class Character'. I'm fairly new to c++ and I don't get why the error was appearing. What I want to do is basically override the GetFierceAttack() of the default Character class to be stronger for the child class which is called Ogre. I was wondering if I was using 'virtual' correctly.
My Character.h file
#ifndef CHARACTER_H
#define CHARACTER_H
#include <time.h>
#include <cstdlib>
class Character
{
protected:
int Health, LightAttack, FierceAttack, Damage;
public:
Character(int health, int lAttack, int fAttack, int damage);
~Character();
public:
int GetHealth() {return Health;}
int GetLightAttack() {return (rand()%5)+10;}
virtual int GetFierceAttack() {return (rand()%5)+10;}
void DeductDamage(int Damage);
};
//Overrides Fierce Attack
class Ogre:public Character
{
public:
Ogre(int health, int lAttack, int fAttack, int damage);
int GetFierceAttack() {return (rand()%10)+20;}
};
#endif
My Chacter.cpp file
#include "Character.h"
//Constructor
Character::Character(int health, int lAttack, int fAttack, int damage)
{
Health = health;
LightAttack = lAttack;
FierceAttack = fAttack;
Damage;
}
//Destructor
Character::~Character()
{
}
void Character::DeductDamage(int Damage)
{
Health -= Damage;
if(Health < 0)
{
Health = 0;
}
}
//Constructor
Ogre::Ogre(int health, int lAttack, int fAttack, int damage) //Here's the error
{
}
//Destructor
Ogre::~Ogre()
{
}
When you define constructor for class by yourself, you are overriding the default implementation.
So you need to provide default constructor as
class Character
{
public:
Character(){}
//----------your code-----//
}
Similarly for your destructor problem you first decalre destructor in class and then define it in .cpp file.
class Ogre:public Character
{
public:
~Ogre();
}
When you declare a non-default constructor for a class, the compiler does not generate a default constructor anymore.
So you have to provide your own.
When you call the constructor on a derived class, what happens is this:
the base object gets constructed first
any variables in the initialisation list get initialised
the body of the (derived) constructor is executed
If you do not specify a different constructor, the default constructor will be used for (1). You are getting a compiler error because you have no default constructor.
To specify a different constructor, do something like this:
Ogre::Ogre(int health, int lAttack, int fAttack, int damage) : Character (health, lAttack, fAttack, damage)
{
// body of constructor
}
Then the instance of the constructor that matches those parameters will be called instead. Since you have defined that, you won't get an error.
As for the error on the destructors, firstly, as others have said, you can't override the destructor without declaring it in the class. So you could add ~Ogre() to your class definition. However, you're not currently doing anything in your destructor body, so why are you redefining it at all? Just leave it as the default destructor.
I am trying the derived class example from TCPL.
Manager is kind of employee with additional info of level. I kept getting the error:
no matching function for call to employee::employee()
in the constructor of manager::manager()
All members of employee are public and accessible. What is wrong with the manager constructor?
#include <iostream>
#include <string>
using namespace std;
class employee{
public:
enum type {M,E};
type hier;
string id;
employee(string idd):hier(E){id=idd;};
};
class manager: public employee{
public:
int level;
manager(string idd, int lv){hier=employee::M; id=idd;level=lv;};
};
void print(employee *x){
if(x->hier == employee::E){
cout<<"I am employee with id "<<x->id<<endl;
}
else{
cout<<"I am manager with id "<<x->id<<endl;
manager* y=static_cast<manager *>(x);
cout<<"My level is "<<y->level<<endl;
}
}
int main(){
employee t("334");
manager u("223", 2);
print(&t);
print(&u);
}
Second version
The previous version was bad in terms of encapsulation
This is the new version
#include <iostream>
using namespace std;
enum type {M, E};
class employee{
string id;
type hier;
public:
employee(string idd, type hi=E):hier(hi),id(idd){}
string whatid(){return id;}
type whattype(){return hier;}
};
class manager: public employee{
int level;
public:
manager(string idd, int lv):employee(idd,M),level(lv){}
int whatlv(){return level;}
};
Instead of directly accessing the private member of employee and manager, I made members private and use a function to access them.
#include <iostream>
#include <string>
#include "manager_employee.h"
using namespace std;
void print(employee *x){
if(x->whattype() == E){
cout<<"I am employee with id "<<x->whatid()<<endl;
}
else{
cout<<"I am manager with id "<<x->whatid()<<endl;
manager *y=(manager *)x;
// manager* y=static_cast<manager *>(x);
cout<<"My level is "<<y->whatlv()<<endl;
}
}
int main(){
employee t("334", E);
manager u("223", 2);
print(&t);
print(&u);
}
By declaring a constructor in employee, you remove its default constructor; so you can't create one without specifying the ID.
This means that any derived classes will need to provide the ID to the base-class constructor:
manager(string idd, int lv) : employee(idd) {hier=employee::M; level=lv;}
// ^^^^^^^^^^^^^
For consistency, you might like to initialise level in the initialiser list rather than the constructor body; and it might make more sense to initialise hier to the correct value via another parameter in the employee constructor, rather than giving it a default value then overwriting it:
employee(string idd, type hier = E) : hier(hier), id(idd) {}
manager(string idd, int lv) : employee(idd, M), level(lv) {}
If you have any explicit constructor for a class, the default constructor goes out of existence.
So for that reason, when you initialize an object of the derived class, it tries to initialize the base class members as well. And as you have not given a constructor taking no arguments, this error is thrown.
Either define a default constructor for employee or try calling the base class constructor as:
manager(string idd, int lv):employee(idd){//your code}
Manager constructor should call base class ctor in its initialization list:
manager(string idd, int lv) : employee(idd) {hier=employee::M; id=idd;level=lv;}
Also consider using initlization list for other members in your classes.
I am having hard time, I am learning classes in C++ now, here is problem I have, I have to declare and define constructor, i dont know what wrong i am doing i tried but could not get the result please help
#include <iostream>
using namespace std;
class exercise
{
public:
//declaration: constructor of class exercise
int public_var;
int get_private_var();
private:
int private_var;
};
//definition: constructor of class exercise
int exercise::get_private_var()
{
return private_var;
}
int main()
{
exercise object(2,3);
int pub_var = object.public_var;
int pri_var = object.get_private_var();
cout << pub_var <<' '<<pri_var<<endl;
return 0;
}
A sample constructor would be:
class exercise
{
public:
exercise(int,int);
int public_var;
int get_private_var();
private:
int private_var;
};
//Constructor definition
exercise::exercise(int a, int b)
{
public_var = a;
private_var = b
}
//rest of member functions
In order to declare a constructor you should
class exercise
{
public:
//declaration: constructor of class exercise
exercise();
int public_var;
int get_private_var();
private:
int private_var;
};
In order to implement (usually in .cpp file)
you should:
exercise::exercise()
{
//your code here
}
good luck
get_private_var is not a constructor. It's function that is called when you do object.get_private_var() - it's just a typical member function.
The constructor is the function that gets called when you construct your object (makes sense, right?). In your case, it would be used when you do:
exercise object(2,3);
This line constructs an exercise object called object and passed the values 2 and 3 to its constructor. It looks like you want to assign those values to the public_var and private_var members.
First you need to declare your constructor:
class exercise
{
public:
exercise(int, int); //declaration: constructor of class exercise
int public_var;
int get_private_var();
private:
int private_var;
};
As you can see, the constructor is declared just like any other member function, except it does not have a return type. That makes sense since the return type is clearly the class itself. Here I have specified two arguments.
Now we need to define the constructor, similar to how you have defined get_private_var, but again with no return type:
exercise::exercise(int x, int y)
{
public_var = x;
private_var = y;
}
And then you're done. This constructor simply assigns the values that are passed to it to the public and private members.
However, there is a slightly better way of implementing this constructor, using a member initialization list:
exercise::exercise(int x, int y)
: public_var(x), private_var(y)
{ }
Here is how you build a class with constructor
class a
{
public:
int pubvar;
a() //default constructor
{
pubvar =1;
privar =2;
}
a(int one, int two) //constructor with intializing
{
pubvar = one;
privar = two;
}
private:
int privar;
}
now default initialization is
a myclass;
and initialize with your variables is
a myclass(4,2);
hope that helps