I have a derived class named TimeWithDate inherited from Date class and Time class.
I try to use the member function by using ::.
like this:
int subtract(TimeWithDate& other_date){
return Date::subtract(other_date) + Time::subtract(other_date);
}
but I got this warning:
Error: a nonstatic member reference must be relative to a specific object.
Then I tried this way:
int subtract(TimeWithDate& other_date){
return *(Date*)this.subtract(other_date) + *(Time*)this.subtract(other_date);
}
and got this warning:
Error: 'this' may only be used inside a nonstatic member function.
What should I do?
whole code
#include<iostream>
using namespace std;
class Time
{
int hour, second, minute;
public:
Time();
Time(int h, int m, int s);
void set(int h, int m, int s);
void increment();
void display();
bool equal(Time &other_time);
bool less_than(Time &other_time);
int subtract(Time &another);
};
class Date
{
int year, month, day;
public:
Date();
Date(int y, int m, int d);
void increment();
bool equal(Date &another);
int subtract(Time &another);
};
class TimeWithDate : public Time, public Date
{
public:
bool compare(TimeWithDate&);
void increment();
int subtract(TimeWithDate&);
};
bool TimeWithDate::compare(TimeWithDate &other_date){
if (Date::equal(other_date) && Time::equal(other_date))
return true;
else return false;
}
void TimeWithDate::increment(){
Time::increment();
Time zero(0, 0, 0);
if (Time::equal(zero))
Date::increment();
}
int subtract(TimeWithDate& other_date){
return Date::subtract(other_date) + Time::subtract(other_date);
}
subtract() should be a member function of class TimeWithDate. It appears that you have it as a non-member/ static function. So, this pointer is no more available in that function.
You need parse your whole code, below works fine in my computer(VS2012).
#include <iostream>
using namespace std;
class Base1
{
public:
void print(const char *str){ cout << "base1 " << str << endl; }
};
class Base2
{
public:
void print(const char *str){ cout << "base2 " << str << endl; }
};
class Derived : public Base1, public Base2
{
public:
void print(const char *str);
};
void Derived::print(const char *str)
{
cout << "Derived " << str << endl;
Base1::print(str);
Base2::print(str);
}
int main()
{
Derived d;
d.print("hello");
return 0;
}
Related
Please see the following code:
// templateClassTemplate.cpp
#include <iostream>
class Account{
public:
explicit Account(double amount=0.0): balance(amount){}
void deposit(double amount){
balance+= amount;
}
void withdraw(double amount){
balance-= amount;
}
double getBalance() const{
return balance;
}
private:
double balance;
};
template <typename T, int N>
class Array{
public:
Array()= default;
int getSize() const;
private:
T elem[N];
};
template <typename T, int N>
int Array<T,N>::getSize() const {
return N;
}
int main(){
std::cout << std::endl;
Array<double,10> doubleArray;
std::cout << "doubleArray.getSize(): " << doubleArray.getSize() << std::endl;
Array<Account,1000> accountArray;
std::cout << "accountArray.getSize(): " << accountArray.getSize() << std::endl;
std::cout << std::endl;
}
This code is taken from a learning course on template initialisation.
I have two questions:
How is the object Array<double,10> doubleArray initialized since it is using a default constructor that takes no arguments?
How is the object Array<Account,1000> accountArray initialized?
The template is instantiated by replacing the type T in the template with the type given as the first argument, and the integer N with the value of the second argument.
The same thing happens when instantiating the definition of getSize.
That is, Array<double,10> doubleArray; works exactly the same as
class DoubleArray10{
public:
DoubleArray10()= default;
int getSize() const;
private:
double elem[10];
};
int DoubleArray10::getSize() const { return 10; }
DoubleArray10 doubleArray;
and Array<Account,1000> accountArray; works exactly like
class AccountArray1000{
public:
AccountArray1000()= default;
int getSize() const;
private:
Account elem[1000];
};
int AccountArray1000::getSize() const { return 1000; }
AccountArray1000 accountArray;
Compiling this code produces the error
error time constructor time::time(int,int,char) cannot be overloaded with time::time(int,int,char)
I'm trying to reduce overloaded constructors so I am trying to give default values in the constructor parameters. Is the line entry(int sno=5,time t{1,2,'p'}); in the constructor for the entry class valid? If a class contains a complex object of another class then can it be initialized this way?
#include<iostream>
using namespace std;
class time
{
int hours;
int mins;
char ap;
public:
time(int hours=0,int mins=0,char ap='n');
time(int a, int b, char c): hours{a},mins{b},ap{c}
{
}
void showtime()
{
cout<<"\nTime : "<<hours<<" "<<mins<<" "<<ap<<endl;
}
};
class entry{
int sno;
time t;
public:
entry(int sno=5,time t{1,2,'p'});
void showdata()
{
cout<<"\ne : "<<sno<<" : ";
t.showtime();
}
};
int main()
{
entry e;
e.showdata();
return 0;
}
Yes it's possible, this is just about syntax :
#include<iostream>
using namespace std;
class Time
{
int _hours;
int _mins;
char _ap;
public:
Time(int hours=0,int mins=0,char ap='n'): _hours(hours),_mins(mins),_ap(ap)
{};
void showtime()
{
cout<<"\nTime : "<< _hours << " " << _mins << " " << _ap << endl;
}
};
class entry{
int _sno;
Time _t;
public:
entry(int sno=5,Time t = Time(1,2,'p')):
_t(t), _sno(sno)
{};
void showdata()
{
cout<<"\ne : "<< _sno<<" : ";
_t.showtime();
}
};
int main()
{
entry e;
e.showdata();
Time t2(5,2,'a');
entry e2(3, t2);
e2.showdata();
return 0;
}
I want to add two numbers using OOP way. I am a complete newbie in C++ and hence need your help.
#include <iostream>
#include <string>
using namespace std;
class RunwalsClass{
public: // public function
void setName(string x){
name = x;
}
string getName(){
return name;
};
private: // good programming practice to make it private
string name;
};
class MyClass{
public:
void setSaying(string y){
CoolSaying = y;
}
string getSaying(){
return CoolSaying;
}
private:
string CoolSaying;
};
class FavSitcom{
public:
void setSitcom(string z){
BreakingBad = z;
}
string getSitcom(){
return BreakingBad;
}
private:
string BreakingBad;
};
class AddClass{
public:
void setNumbers(int a, int b){
int answer = a + b;
}
int getAddition(){
return answer;
}
private:
int answer;
};
int main(){
RunwalsClass RunwalsObject;
RunwalsObject.setName("Sir Buckey Wallace");
cout << RunwalsObject.getName() << endl;
MyClass MyObject;
MyObject.setSaying("Preaching to the choir! \n");
cout << MyObject.getSaying();
FavSitcom MyNewObject;
MyNewObject.setSitcom("My favorite Sitcom is: Breaking Bad \n");
cout << MyNewObject.getSitcom();
AddClass NewObject;
NewObject.setNumbers("answer: \n");
cout << AddObject.getAddition();
return 0;
}
error: #include <iostream>
#include <string>
using namespace std;
class RunwalsClass{
public: // public function
void setName(string x){
name = x;
}
string getName(){
return name;
};
private: // good programming practice to make it private
string name;
};
class MyClass{
public:
void setSaying(string y){
CoolSaying = y;
}
string getSaying(){
return CoolSaying;
}
private:
string CoolSaying;
};
class FavSitcom{
public:
void setSitcom(string z){
BreakingBad = z;
}
string getSitcom(){
return BreakingBad;
}
private:
string BreakingBad;
};
class AddClass{
public:
void setNumbers(int a, int b){
int answer = a + b;
}
int getAddition(){
return answer;
}
private:
int answer;
};
int main(){
RunwalsClass RunwalsObject;
RunwalsObject.setName("Sir Buckey Wallace");
cout << RunwalsObject.getName() << endl;
MyClass MyObject;
MyObject.setSaying("Preaching to the choir! \n");
cout << MyObject.getSaying();
FavSitcom MyNewObject;
MyNewObject.setSitcom("My favorite Sitcom is: Breaking Bad \n");
cout << MyNewObject.getSitcom();
AddClass NewObject;
NewObject.setNumbers("answer: \n");
cout << AddObject.getAddition();
return 0;
}
Reported error:
error: no matching function for call to 'AddClass::setNumbers(const char [10])
note: candidate: void AddClass::setNumbers(int, int)
note: candidate expects 2 arguments, 1 provided.
In main, your are passing a string as parameter to your setNumbers method. This line is wrong in main:
NewObject.setNumbers("answer: \n");
Your setNumbers function neeeds 2 integers as it is declared. Try:
int a = 10;
int b = 5;
NewObject.setNumbers(a, b);
Good luck in your OOP learning journey!
EDIT:
Also, in your setNumbers function, you must not redeclare answer because this variable is a class member. Remove int, just use answer inside setNumbers.
Yep so your function setNumbers() expects two integer arguments provided, i.e. NewObject.setNumbers(5, 10); which would set the number to 15. You have provided a string literal "answer: \n" which is not the same and therefore will not compile.
Program works but I am not sure what is wrong with constructor since every time program runs it gets this error "warning: base class 'Alat' is uninitialized when used here to access 'Alat::ime' [-Wuninitialized]". I suppose it's something wrong how I called a constructor from base class but I am not sure what is problem. Really need help, tnx in advance.
#include <iostream>
#include <string>
using namespace std;
class Alat{
protected:
string ime;
int serBr;
int cena;
public:
void setIme(string i);
string getIme();
void setSerBr(int sb);
int getSerBr();
void setCena(int c);
int getCena();
Alat();
Alat(string i, int sb, int c)
:ime(i),
serBr(sb),
cena(c)
{}
void info();
~Alat();
};
#include "Alat.h"
class Rucni : public Alat{
protected:
int minGodKor;
public:
Rucni():Alat(ime, serBr, cena) //I think here is problem, is it wrong called?
{}
int getminGodKor();
void setminGodKor(int min);
void info();
~Rucni();
};
Let the child default constructor call the default parent constructor, and create another child constructor with parameters to call the corresponding one of the parent:
#include <string>
using std::string;
class Alat
{
protected:
string ime;
int serBr;
int cena;
public:
void setIme(string i)
{
ime = i;
}
string getIme()
{
return ime;
}
void setSerBr(int sb)
{
serBr = sb;
}
int getSerBr()
{
return serBr;
}
void setCena(int c)
{
cena = c;
}
int getCena()
{
return cena;
}
Alat()
{
}
Alat(string i, int sb, int c) : ime(i), serBr(sb), cena(c)
{
}
~Alat()
{
}
};
class Rucni : public Alat
{
protected:
int minGodKor;
public:
Rucni() // implicit call of the parent default constructor
{
}
Rucni(string i, int sb, int c) : Alat(i, sb, c) // explicit call of the corresponding parent constructor
{
}
int getminGodKor()
{
return minGodKor;
}
void setminGodKor(int min)
{
minGodKor = min;
}
~Rucni()
{
}
};
int main()
{
Rucni r;
return 0;
}
From my code below I'm trying to create a Course grading system. So, it will store the type of assignment, its weightage and the achieved grade. I'm trying to get it to print the raw score (which is the grade entered for example: "B-" or 85.50; depending on whether it is an exam or quiz).
I have read about "casting" which should resolve the issue of using void* as a pointer but I am still unclear as to how I can implement it. I tried static_cast<struct Grading*>(c.gs[0])(commented out in code) but it still returned the address of the value, instead of the value itself. Any help will be appreciated. Thanks in advance!
#include <iostream>
#include <vector>
using namespace std;
struct Grading{
string name;
int percentage;
virtual ~Grading(){}
virtual void* get_raw_score(){return 0;}
void* get_adj_score(){return 0;}
};
struct Quiz:public Grading{
string letter_grade;
Quiz(const string title, const int weight, const string grade){
name=title;
percentage=weight;
letter_grade=grade;
}
virtual void* get_raw_score(){return &letter_grade;}
};
struct Exam:public Grading{
double *score = new double;
Exam(const string title, const int weight, const double grade){
name=title;
percentage=weight;
*score=grade;
}
virtual void* get_raw_score(){return &score;}
};
struct Project:public Grading{
string letter_grade;
Project(const string title, const int weight, const string grade){
name=title;
percentage=weight;
letter_grade=grade;
}
virtual void* get_raw_score(){return &letter_grade;}
};
struct CourseWork{
vector<Grading*> gs;
void push_back(Grading* g){
gs.push_back(g);
}
void sort_name(){}
void sort_score(){}
};
ostream& operator<<(ostream& o,const CourseWork c){ //output the raw score here.
//static_cast<struct Grading*>(c.gs[0]);
o<<c.gs[0]->name<<endl<<c.gs[0]->percentage<<c.gs[0]->get_raw_score()<<endl;
return o;
}
int main() {
CourseWork c;
c.push_back(new Quiz("Quiz", 5, "B-"));
c.push_back(new Quiz("Quiz", 5, "C+"));
c.push_back(new Quiz("Quiz", 5, "A"));
c.push_back(new Exam("Midterm", 10, 50));
c.push_back(new Exam("Final", 30, 85.5));
c.push_back(new Project("Project", 5, "A-"));
c.push_back(new Project("Project", 15, "B-"));
c.push_back(new Project("Project", 15, "B-"));
c.push_back(new Project("Demo", 10, "C"));
cout << "** Showing populated data..." << endl;
cout << c << endl << endl;;
c.sort_name();
cout << "** Showing sorted by name..." << endl;
cout << c << endl << endl;
c.sort_score();
cout << "** Showing sorted by score..." << endl;
cout << c << endl;
return 0;
}
Instead of writing a function that returns a void* and trying to figure out what it actually returns you can make the function return a string in all cases but when it is a number just convert the number to a string. You could use:
struct Grading{
string name;
int percentage;
virtual ~Grading(){}
virtual std::string get_raw_score() = 0; //make pure virtual since we only use Grading as a base class
void* get_adj_score(){return 0;}
};
struct Quiz:public Grading{
string letter_grade;
Quiz(const string title, const int weight, const string grade){
name=title;
percentage=weight;
letter_grade=grade;
}
virtual std::string get_raw_score(){return letter_grade;}
};
struct Exam:public Grading{
double score; // this does not need to be a pointer
Exam(const string title, const int weight, const double grade){
name=title;
percentage=weight;
score=grade; // no more dereference
}
virtual std::string get_raw_score(){return std::stod(score);} // now the score is represented as a string
};
struct Project:public Grading{
string letter_grade;
Project(const string title, const int weight, const string grade){
name=title;
percentage=weight;
letter_grade=grade;
}
virtual std::string get_raw_score(){return letter_grade;}
};
struct CourseWork{
vector<Grading*> gs;
void push_back(Grading* g){
gs.push_back(g);
}
void sort_name(){}
void sort_score(){}
};
ostream& operator<<(ostream& o,const CourseWork c){ //output the raw score here.
//static_cast<struct Grading*>(c.gs[0]);
o<<c.gs[0]->name<<endl<<c.gs[0]->percentage<<c.gs[0]->get_raw_score()<<endl;
return o;
}
You can make your base class abstract and use a template parameter instead of using a void* pointer:
struct IGrading {
virtual const std::string get_raw_score() const = 0;
};
template<typename T>
class Grading : public IGrading {
public:
virtual ~Grading() {}
};
std::ostream& operator<<(std::ostream& os, const IGrading& g) {
os << g.get_raw_score();
return os;
}
and derive your implementations as needed to implement the interface contract
class Quiz : public Grading<std::string> {
public:
Quiz(std::string title, int weight, std::string rawScore)
: title_(title)
, weight_(weight).
, rawScore_(rawScore) {}
virtual const std::string& get_raw_score() const {
return rawScore_;
}
private:
std::string title_;
int weight_;
std::string rawScore_;
};
... and analogous implementations:
class Exam : public Grading<double> {
public:
Exam(std::string title, int weight, double rawScore)
: title_(title)
, weight_(weight)
, rawScore_(rawScore) {}
virtual const std::string& get_raw_score() const {
return std::to_string(rawScore_);
}
private:
double rawScore_;
};
Or have a generic base class implementation for numeric template parameters:
template<typename T>
class NumericGrading : public Grading<T> {
protected:
NumericGrading(T rawScore) : rawScore_(rawScore) {}
public:
virtual const std::string& get_raw_score() const {
return std::to_string(rawScore_);
}
protected:
T rawScore_;
};
and let Exam derive that:
class Exam : public NumericGrading<double> {
public:
Exam(std::string title, int weight, double rawScore)
: NumericGrading<double>(rawScore)
, title_(title)
, weight_(weight) {}
};
This will keep your code type safe and avoid any weird and error prone casting operations.
The CourseWork container can use the abstract interface:
struct CourseWork{
vector<IGrading*> gs;
void push_back(IGrading* g){
gs.push_back(g);
}
void sort_name(){}
void sort_score(){}
};