#include <iostream>
#include <vector>
using namespace std;
class MainClass{
public:
virtual void getData() = 0;
virtual void printData() = 0;
};
class Car : public MainClass{
private:
int hp;
int motor;
public:
Car(int _hp = 0, int _motor = 0){
hp = _hp;
motor = _motor;
}
~Car(){
cout << "The program is over";
}
void getData(){
cout << "HorsePower = ";
int _hp;
cin >> _hp;
hp = _hp;
cout << "Motor = ";
int _motor;
cin >> _motor;
motor = _motor;
}
void printData(){
cout << "HorsePower = " << hp << '\n';
cout << "Motor = " << motor << '\n';
}
float procent(){
return float(motor) / hp;
}
};
int main()
{
MainClass *p = new Car;
p -> getData();
p -> printData();
cout << p -> procent();
return 0;
}
I'm pretty new with oop concepts so why do I get the error from title and how can i solve it? I tried to put virtual float procent() = 0 in MainClass, but then i should use this function in every class that i would create next and I dont want this.
procent() is not a member of class MainClass.
The pointee type of p is MainClass.
Hence, you can only access what is known in MainClass.
That the pointer p actually holds an address of a Car instance doesn't count for this.
getData() and printData() are known but procent() not. (It's part of the derived class Car.)
That you can access Cars overridden getData() and printData() by the MainClass pointer p is a result of the (wonderful world of) polymorphy i.e. they are virtual.
So, this is a potential solution – to make procent() a virtual member function of MainClass as well.
There is still another solution but it should be used as last resort only:
You can use dynamic_cast() to check whether/that p holds actually a pointer to an instance of class Car:
#include <iostream>
#include <vector>
using namespace std;
class MainClass{
public:
virtual void getData() = 0;
virtual void printData() = 0;
};
class Car : public MainClass{
private:
int hp;
int motor;
public:
Car(int _hp = 0, int _motor = 0){
hp = _hp;
motor = _motor;
}
~Car(){
cout << "The program is over";
}
void getData(){
cout << "HorsePower = ";
int _hp;
cin >> _hp;
hp = _hp;
cout << "Motor = ";
int _motor;
cin >> _motor;
motor = _motor;
}
void printData(){
cout << "HorsePower = " << hp << '\n';
cout << "Motor = " << motor << '\n';
}
float procent(){
return float(motor) / hp;
}
};
int main()
{
MainClass *p = new Car;
p -> getData();
p -> printData();
if (Car *pCar = dynamic_cast<Car*>(p)) {
cout << pCar -> procent();
}
return 0;
}
Output:
HorsePower = 300
Motor = 6
HorsePower = 300
Motor = 6
0.02
Live Demo on coliru
The solution with dynamic_cast may be preferable for large class inheritance trees where it's merely impractical to add virtual member functions to the base class for any (exotic) specific feature of derived classes.
The error happens because your trying to access the procent() method in the MainClass object. To resolve this, you need to add it as a virtual method in the MainClass and override it in the Car object.
Plus make sure to delete the allocated memory.
#include <iostream>
#include <vector>
using namespace std;
class MainClass{
public:
virtual void getData() = 0;
virtual void printData() = 0;
virtual void procent() = 0;
};
class Car : public MainClass {
private:
int hp;
int motor;
public:
Car(int _hp = 0, int _motor = 0){
hp = _hp;
motor = _motor;
}
~Car(){
cout << "The program is over";
}
void getData() override {
cout << "HorsePower = ";
int _hp;
cin >> _hp;
hp = _hp;
cout << "Motor = ";
int _motor;
cin >> _motor;
motor = _motor;
}
void printData() override {
cout << "HorsePower = " << hp << '\n';
cout << "Motor = " << motor << '\n';
}
float procent() override {
return float(motor) / hp;
}
};
int main()
{
MainClass *p = new Car;
p -> getData();
p -> printData();
cout << p -> procent();
delete p;
return 0;
}
The reason for the error is that when you assign the data of the derived class to the base class pointer, the data accessed from the base class pointer is treated as if its from the base class. And since the method procent() is not available in it, the error is flagged.
TIP:
Even though stating override in the overridden method is not necessary, it'll definitely increase the readability of your code.
Related
#include <iostream>
using namespace std;
class Student
{
protected:
long studentID;
public:
void setStudentID(long s_){ studentID = s_; }
Student(): studentID(0){}
long get_StudentID(){ return studentID; }
};
class Exam : public Student
{
protected:
float mark;
public:
void setMark(float m_){ mark = m_; }
Exam(): mark(0){}
float getMark(){ return mark; }
};
class Sports : public Student
{
protected:
float score;
public:
void setScore(float s_){ score = s_; }
Sports(): score(0){}
float getScore(){ return score; }
};
class Result: public Student, public Exam, public Sports
{
private:
float Total;
public:
float getTotal(){ return getMark() * getScore(); }
void display();
};
void Result::display()
{
cout << "Student ID = " << get_StudentID() << endl;
cout << "Exam Mark = " << getMark() << endl;
cout << "Sports Score = " << getScore() << endl;
cout << "Total Mark = " << getTotal();
}
int main()
{
Result st1;
st1.display();
return 0;
}
I wrote this code in Code::Blocks and it's incomplete yet , but this error that says "refrence to get_StudentID is ambigous" confused me; What's wrong with it?
Should I delete using namespace and insert std:: before all (cout, cin & endl) statments?
You are misunderstanding inheritance. For example, the class Exam with this line
class Exam : public virtual Student
is publicly inheriting from Student. Public inheritance should only be used in an IS-A relationship. In this case, Exam is not a Student so you shouldn't use public inheritance. Same goes for Sports.
"Call is ambiguous" means that when you call get_StudentID from Result the compiler can't decide between Exam::get_StudentID or Sports::get_StudentID which they both inherit from Student.
Instead:
Remove the inheritance, don't use inheritance anywhere here. I would completely remake this and make a Student class with Exam and Sports member objects (which can become vector of objects later if needed) and call the needed functions from the member objects instead. As a general tip, avoid multiple inheritance unless completely necessary.
This is an easy fix
remove Student from Results base class
make Student public virtual from both Exam and Sports class
#include <iostream>
using namespace std;
class Student
{
protected:
long studentID;
public:
void setStudentID(long s_){ studentID = s_; }
Student(): studentID(0){}
long get_StudentID(){ return studentID; }
};
class Exam : public virtual Student
{
protected:
float mark;
public:
void setMark(float m_){ mark = m_; }
Exam(): mark(0){}
float getMark(){ return mark; }
};
class Sports : public virtual Student
{
protected:
float score;
public:
void setScore(float s_){ score = s_; }
Sports(): score(0){}
float getScore(){ return score; }
};
class Result: public Exam, public Sports
{
private:
float Total;
public:
float getTotal(){ return getMark() * getScore(); }
void display();
};
void Result::display()
{
cout << "Student ID = " << get_StudentID() << endl;
cout << "Exam Mark = " << getMark() << endl;
cout << "Sports Score = " << getScore() << endl;
cout << "Total Mark = " << getTotal();
}
int main()
{
Result st1;
st1.display();
return 0;
}
Godbolt: https://godbolt.org/z/4f5n8M5of
When I tried to convert it the class result can't get the data from class marks even if I made the data variables of marks public I don't know why. I also declared a object of class marks in result and then tried to access it but failed again I am new to coding so don't know all the syntax correctly your help will be of great use
#include <string.h>
#include <iostream>
using namespace std;
class student {
private:
int rl;
char nm[20];
public:
void read();
void display();
};
class marks : public student {
protected:
int s1;
int s2;
int s3;
public:
void getmarks();
void putmarks();
};
class result : public marks {
private:
int t;
float p;
char div[10];
public:
void process();
void printresult();
};
void student::read() {
cout << "enter Roll no and Name " << endl;
cin >> rl >> nm;
}
void student::display() {
cout << "Roll NO:" << rl << endl;
cout << "name : " << nm << endl;
}
void marks ::getmarks() {
cout << "enter three subject marks " << endl;
cin >> s1 >> s2 >> s3;
}
void marks ::putmarks() {
cout << "subject 1:" << s1 << endl;
cout << "subject 2 :" << s2 << endl;
cout << "subject 3:" << s3 << endl;
}
void result::process() {
t = s1 + s2 + s3;
p = t / 3.0;
p >= 60 ? strcpy(div, "first")
: p >= 50 ? strcpy(div, "second")
: strcpy(div, "third");
}
void result::printresult() {
cout << "total = " << t << endl;
cout << "per = " << p << "%" << endl;
cout << "div = " << div << endl;
}
int main(){
result x;
x.read();
x.getmarks();
x.process();
x.display();
x.putmarks();
x.printresult();
}
#include<iostream>
#include<string.h>
using namespace std;
class marks // parent class
{
protected:
int s1;
int s2;
int s3;
public:
void getmarks();
void putmarks();
};
class student : public marks // child class
{
private:
int rl;
char nm[20];
public:
void read();
void display();
};
class result : public marks// child class
{
private:
int t;
float p;
char div[10];
public:
void process();
void printresult();
};
void student::read()
{
cout<<"enter Roll no and Name "<<endl;
cin>>rl>>nm;
}
void student:: display()
{
cout <<"Roll NO:"<<rl<<endl;
cout<<"name : "<<nm<<endl;
}
void marks ::getmarks()
{
cout<<"enter three subject marks "<<endl;
cin>>s1>>s2>>s3;
}
void marks ::putmarks()
{
cout <<"subject 1:"<<s1<<endl;
cout<<"subject 2 :"<<s2<<endl;
cout <<"subject 3:"<<s3<<endl;
}
void result::process()
{
t= s1+s2+s3;
p = t/3.0;
p>=60?strcpy(div,"first"):p>=50?strcpy(div, "second"): strcpy(div,"third");
}
void result::printresult()
{
cout<<"total = "<<t<<endl;
cout<<"per = "<<p<<"%"<<endl;
cout<<"div = "<<div<<endl;
}
int main()
{
result x;
student y;
y.read();
x.getmarks();
x.process();
y.display();
x.putmarks();
x.printresult();
}
I am trying to call all the virtual functions in the derived class and then define them outside as the saving class, however I am looks like I am not properly defined my constructor class and I cannot seem to fix it.
I am using the constructor from class accountInfo to store the virtual functions and the protected members and I want balance to update using saving(current_balance,current_interest);. However, I am sure I have a logical error somewhere but I cannot find it. I know I do not use the constructor accountInfo(double addBalance, double intRate); because I want to update the value of balance using the derived class not the parent class
#include <iostream>
#include <math.h>
#include <string>
using namespace std;
class accountInfo{
public:
accountInfo();
accountInfo(double addBalance, double intRate);
virtual void deposit(double amount);
virtual void withdraw(double amount);
virtual double calcInt();
virtual double monthlyProc();
void virtual print();
~accountInfo();
protected:
double balance = 0;
int numDeposits = 0;
int numWithdraws = 0;
double annual_Interest = 0;
double monthlyServiceFee = 10;
bool status = false;
};
class saving: public accountInfo{
public:
saving(double addBalance, double intRate);
void print();
void withdraw(double amount);
void deposit(double amount);
double calcInt();
double monthlyProc();
};
void saving::deposit(double amount){ //how to call back the base function
if(balance >=25){
status = true;
balance +=amount;
numDeposits++;
}
else
status = false;
cout << "Balance is below 25" << endl;
}
accountInfo::accountInfo(){}
accountInfo::accountInfo(double addBalance, double intRate){
balance = addBalance;
annual_Interest = intRate;
}
saving::saving(double addBalance, double intRate){
balance = addBalance;
annual_Interest = intRate;
}
void saving::withdraw(double amount){
balance -= amount;
numWithdraws++;
}
double saving::calcInt(){
double monthlyRate = annual_Interest/12;
double monthlyInterest = balance * monthlyRate;
return balance + monthlyInterest;
}
double saving::monthlyProc(){ //how to call calcInt to delete the following
balance -= monthlyServiceFee;
numWithdraws = 0;
numDeposits = 0;
monthlyServiceFee = 0;
return balance;
}
void saving::print(){
cout <<"current balance " <<balance << endl;
cout << "Interest Rate "<<annual_Interest << endl;
cout << "number of deposits " << numDeposits << endl;
cout << "number of withdraws " << numWithdraws << endl;
cout << "monthlyServiceFee " << monthlyServiceFee << endl;
}
accountInfo::~accountInfo(){}
int main(){
double current_balance = 0;
double current_interest = 0;
double money, money0;
//accountInfo obj0;
accountInfo obj = accountInfo(100,100);
char option;
while(option != 'Q'){
cout << "Select action" << endl;
cin >> option;
option = toupper(option);
saving obj1(current_balance,current_interest);
switch(option){
case('A'):
{
cout << "Please input your balance and interest rate: " << endl;
cin >> current_balance;
cin >> current_interest;
obj1 = saving(current_balance,current_interest);
}
break;
case('D'):
cout << "Money to deposit" << endl;
cin >> money;
obj1.deposit(money);
break;
case('W'):
cout << "Money to withdraw" << endl;
cin >> money0;
obj1.withdraw(money0);
break;
case('P'):
obj1.print();
break;
case ('Q'):
option = 'Q';
break;
}
}
// cout << "the balance after interest is " <<obj.calcInt() << endl;
// cout << "money after the monthly services " << obj.monthlyProc() << endl;
return 0;
}
If you ever have a class:
class Base {
public:
Base();
};
and some other derived class:
class Derived : public Base{
public:
Derived();
};
The proper way to call a parent class' constructor is like this:
Derived::Derived() : Base() {
// Some implementation
}
So you call the constructor after a :. So in your case, it would probably look something like this:
saving::saving(double addBalance, double intRate) : accountInfo(addBalance, intRate) {
// Some implementation
}
This will call accountInfo()'s constructor when saving() is constructed.
Im trying to solve a problem in C++ but because im a begginer i dont know how to do it !
The problem is this if you can help me :) :
By using the below C++ code create the proper constructor functions about the classes "car" & "truck". Each function must pass the appropriate arguments to the parent class of vehicle.Additionally, the function car should initialize the passengers when creating an object. The truck class should initialize the loadlimit when creating an object.
The statement of objects with the car () and truck () will be as follows:
car ob(passengers, wheels, range);
truck ob(loadlimit, wheels, range);
#include <iostream>
using namespace std;
class vehicle{
int num_wheels;
int range;
public:
vehicle(int w, int r){num_wheels = w; range = r;}
void showv(){
cout << "Wheels: " << num_wheels << endl;
cout << "Range: " << range << endl;
}
};
class car : public vehicle {
int passengers;
public:
void show(){
void showv();
cout << "Passengers: " << passengers << endl;
}
};
class truck : public vehicle {
int loadlimit;
public:
void show(){
void showv();
cout << "Loadlimit: " << loadlimit << endl;
}
};
int main(){
car c(5, 4, 500);
truck t(3000, 12, 1200);
cout << "Car: " << endl;
c.show();
cout << "Truck: " << endl;
t.show();
return 0;
}
Class Car and Truck does not have constructors that take required parameters and pass to the base class's constructor. they should be like this:
class car : public vehicle {
int passengers;
public:
car(int w,int r,int p): vehicle(w,r), passengers(p){}
void show(){
void showv();
cout << "Passengers: " << passengers << endl;
}
};
class truck : public vehicle {
int loadlimit;
public:
truck(int r, int w, int l):vehicle(r,w),loadlimit(l){}
void show(){
void showv();
cout << "Loadlimit: " << loadlimit << endl;
}
};
Base member initialisation
Car Constructor:
car(int a, int b, int c) : vehicle(a,b),passengers(c){}; //initialiser list
Truck Constructor:
truck(int g, int h, int j):vehicle(g,h),loadlimit(j){}
You need to add a Contractor to car and truck
class car : public vehicle {
int passengers;
public:
car(int p) : vehicle(int w, int r) // Call the superclass constructor in the subclass'
{
passengers = p;
}
void show()
{
showv();
cout << "Passengers: " << passengers << endl;
}
};
The same thing for Truck
Simple Solution,
car::car(int w,int r,int p)
{
passengers = p;
vehicle::vehicle(w,r);
}
//QuizShape.h
#ifndef QUIZSHAPE_H
#define QUIZHAPE_H
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
class QuizShape
{
protected:
//outer and inner symbols, and label
char border, inner;
string quizLabel;
public:
//base class constructor with defaults
QuizShape(char out = '*', char in = '+', string name = "3x3 Square")
{
border = out;
inner = in;
quizLabel = name;
cout << "base class constructor, values set" << endl << endl;
};
//getters
char getBorder() const
{ return border; }
char getInner() const
{ return inner; }
string getQuizLabel() const
{ return quizLabel; }
//virtual functions to be defined later
virtual void draw( ) = 0;
virtual int getArea( ) = 0;
virtual int getPerimeter( ) = 0;
};
class Rectangle : public QuizShape
{
protected:
//height and with of a rectangle to be drawn
int height, width;
public:
//derived class constructor
Rectangle(char out, char in, string name,
int h = 3, int w = 3):QuizShape(out, in, name)
{
height = h;
width = w;
cout << "derived class constructor, values set" << endl << endl;
}
//getters
int getHeight() const
{ return height; }
int getWidth() const
{ return width; }
//*********************************************
virtual void draw(const Rectangle &rect1)
{
cout << "draw func" << endl;
cout << rect1.height << endl;
cout << rect1.getWidth() << endl;
cout << rect1.getQuizLabel() << endl;
}
virtual int getArea(const Rectangle &rect2)
{
cout << "area func" << endl;
cout << rect2.getInner() << endl;
cout << rect2.getBorder() << endl;
}
virtual int getPerimeter(const Rectangle &rect3)
{
cout << "perim func" << endl;
cout << rect3.height << endl;
cout << rect3.getWidth() << endl;
cout << rect3.getQuizLabel() << endl;
}
//************************************************
};
#endif
These are the class types so far.
//QuizShape.cpp
#include "QuizShape.h"
This currently does nothing but bridge the files.
//pass7.cpp
#include "QuizShape.cpp"
int main()
{
Rectangle r1('+', '-', "lol", 4, 5);
cout << r1.getHeight() << endl;
cout << r1.getWidth() << endl;
cout << r1.getInner() << endl;
cout << r1.getBorder() << endl;
cout << r1.getQuizLabel() << endl;
system("pause");
return 0;
}
The code will not compile due to the fact that Rectangle is supposedly an abstract class, and when hovering over the declaration of r1 in main, I receive the error
"Object of abstract class type "Rectangle" is not allowed".
I have checked other answers on this site and others and have not come across something that solves the problem.
NOTE: I understand that the statements for virtual functions ending in =0; cause the class to become an abstract one. QuizShape SHOULD be abstract. I have defined the virtual functions in Rectangle and yet it remains an abstract class.
How can I modify the virtual functions Rectangle class so that Rectangle is no longer abstract?
Your methods int the abstract class QuizShape are:
virtual void draw( ) = 0;
virtual int getArea( ) = 0;
virtual int getPerimeter( ) = 0;
but in Rectangle they take const Rectangle &rect1 as parameter so you shadowing the methods and not overriding the abstract one at all. You need to have methods in Rectangle with the same signature as the ones in the abstract base class.
The overridden methods must have the exact same signature, in the derived class you have given them arguments.