"static_cast" with pointers and objects in C++ - c++

I've just learnt about inheritance and started using casting. While I was messing around trying to get to know the topic I found myself facing this problem which I couldn't explain. Here's the code:
#include <iostream>
#include <string>
using namespace std;
__interface AbstractClass {
void Eat()const;
void Sleep()const;
void Work()const;
string Info();
};
class Employee : public AbstractClass {
private:
string lastName;
int age, salary;
static int EmpCounter;
protected:
string name;
public:
Employee(string n = "Avto", string ln = "Chachandize", int a = 18, int s = 3000)
: name(n), lastName(ln), age(a), salary(s) {
EmpCounter++;
}
virtual ~Employee() {
EmpCounter--;
}
static int getEmpCounter() {
return EmpCounter;
}
void Eat()const override {
cout << name << " Is eating" << endl;
}
void Sleep()const override {
cout << name << " Is sleeping" << endl;
}
void Work()const override {
cout << name << " Is doing his/her stuff" << endl;
}
string Info() override {
string a = to_string(age);
string s = to_string(salary);
return name + ' ' + lastName + ' ' + a + ' ' + s + ' ';
}
};
int Employee::EmpCounter = 0;
class Developer : public Employee {
string language;
public:
Developer(string n = "Avto", string ln = "Chachandize", int a = 18, int s = 3000, string l = "C++") :
Employee(n, ln, a, s), language(l) {}
~Developer()override = default;
void Work()const override {
cout << name << " Is writing code in " << language << endl;
}
string Info() override {
Employee* emp = static_cast<Employee*>(this);
//Employee emp = static_cast<Employee>(*this);
return emp->Info() + ' ' + language;
}
};
int main() {
Developer dev;
cout << dev.Info() << endl;
}
I was trying to upcast Developer to Employee and then get his info. However static cast with pointers gives me error .
Strangely, second one which is commented doesn't. I don't know what is the reason of that. I also tried it with reference and there's also error. Same thing happened while using dynamic cast.
string Info() override {
Employee* emp = static_cast<Employee*>(this);
//Employee emp = static_cast<Employee>(*this);
return emp->Info() + ' ' + language;
}
So my question is, is that supposed to be an error or not?

As it was suggested you do not need to use casts when you want to get pointer to object to base class from the pointer to object to child class.
But it seems you want to call "Info" method of base class ("Employee") inside the body of "Info" method of the child class ("Developer"). It can be done in the following way:
Employee::Info();
for example in your case:
string Info() override {
return Employee::Info() + ' ' + language;
}

Related

Why may a class trying to change a value in a friendly class's field be triggernig an error?

So I've been learning how friendly classes work, and I created two classes, both being friendly to one another. Howewer, as soon as I write a method to modify a value in another class's field, I get a compilator error, and Visual Studio refuses to elaborate on how to fix it. Here is the code:
#include <iostream>
#include <cstring>
using namespace std;
class Human;
class Apple;
class Human
{
public:
Human();
Human(int bitepower, string& name);
void BiteApple(Apple& other)
{
other.weight -= this->bitepower;
}
void Print()
{
cout << "Имя = " << this->name << " Сила укуса = " << this->bitepower << " id = " << this->id << endl;
}
~Human();
private:
friend Apple;
int bitepower;
string name;
int id;
static int num;
};
Human::Human()
{
bitepower = 0;
num++;
id = num;
name = string("Unidentified " + id);
}
Human::Human(int test, string& name)
{
this->bitepower = test;
num++;
id = num;
this->name = name;
}
int Human::num = 0;
Human::~Human()
{
}
class Apple
{
public:
Apple();
Apple(int weight);
void Print()
{
cout << "Apple id = " << this->id << " Weight = " << this->weight << endl;
}
~Apple();
private:
friend Human;
int weight;
static int num;
int id;
};
Apple::Apple()
{
weight = 0;
num++;
id = num;
}
Apple::Apple(int weight)
{
this->weight = weight;
num++;
id = num;
}
int Apple::num = 0;
Apple::~Apple()
{
}
int main()
{
//Apple apple1(80);
//Human egor(20, "Егор");
//egor.Print();
//apple1.Print();
//egor.BiteApple(apple1);
//egor.Print();
//apple1.Print();
return 0;
}
And this is the exact method that causes everything to stop working:
void BiteApple(Apple& other)
{
other.weight -= this->bitepower;
}
After I've localised the problem, I've tried moving the announcements of the classes around, and outlining the very function to be friendly, but to no effect. I just can't seem to find the answer nowhere.
Here is the exact error I get:enter image description here
This reads as: Compilation error occured. Continue and load the last succsessfully built version?
I have also tried moving the declaration of Apple class below the declaration of Human class as suggested, but it had no effect. I would be grateful to be advised if this can be solved without creating a header file as I have not learned this yet, and if not, I'll need to learn file structure and return to friendly classes later.

How to execute a class method by string input in C++

I am trying to develop a text adventure in C++ where users can input string commands (ex. "take apple").
Here is a very naive sample of code I came up with:
# include <iostream>
using namespace std;
class fruit{
public:
string actual_name;
fruit(string name){
actual_name = name;
}
take() {
cout << "You take a " << actual_name << "." << endl;
}
};
fruit returnObjectFromName(string name, fruit Fruits[]){
for(int i = 0; i <= 1; i++){ // to be modified in future depending on Fruits[] in main()
if (Fruits[i].actual_name == name)
return Fruits[i];
}
}
int main(){
string verb;
cout << "Enter verb: ";
cin >> verb;
string object;
cout << "Enter object: ";
cin >> object;
fruit apple("apple");
fruit Fruits[] = { apple }; // to be extended in future
// returnObjectFromName(object, Fruits). ??? ()
}
How can I possibly get the fruit method with something similar to the function returnObjectFromName, if this is even possible?
I began the development with Python (independently), and there I can at least use eval(), but as I understand in C++ this is not an option.
I tried also with map, but I didn't manage to make it work with methods.
Thank you all for your answers.
Its not good way to rely on reflection in C++ and i think there is no way to list methods in classes. Maybe you can use function pointers but pointer to instance methods are hell.
I recommend to use polymorphism and good design. If some items might be taken, then use interface like this:
#include <iostream>
using namespace std;
class ITakeable {
public:
virtual bool isTakeable() = 0;
virtual void take() = 0;
virtual void cannotTake() = 0;
};
class fruit : public ITakeable {
public:
string actual_name;
fruit(string name){
actual_name = name;
}
bool isTakeable() {
return true;
}
void take() {
cout << "You take a " << actual_name << "." << endl;
}
void cannotTake() {
cout << "not needed to be implemented";
}
};
class airplane : public ITakeable {
public:
string actual_name;
airplane(string name){
actual_name = name;
}
bool isTakeable() {
return false;
}
void take() {
cout << "not needed to be implemented";
}
void cannotTake() {
cout << "You CANNOT take a " << actual_name << "." << endl;
}
};
int main() {
fruit apple("apple");
if (apple.isTakeable()) {
apple.take();
}
airplane plane("boeing");
if (plane.isTakeable()) {
plane.take();
} else {
plane.cannotTake();
}
// use of interface in general
ITakeable * something = &apple;
if (something->isTakeable()) {
something->take();
}
something = &plane;
if (something->isTakeable()) {
something->take();
} else {
something->cannotTake();
}
return 0;
}
Since fruit is a user defined type, you have to declare your own methods for your type or you inherit from one previously defined.
There are a lot of method for "built-in" string type
that Performs virtually the same job as eval (...) in python.
Also I noticed your function need not be defined independently outside of class fruit.

Is it possible to use same functions for every class

I have multiple classes and each of them has their own methods. All of these methods perform the same task, as you can see in my code. The only unique thing is the values of the title, code and credit members that are defined inside the classes.
Is there a way to write this code such that a single set of methods can do the required tasks (using the specific values within the class that made the request to the method) for each and every class?
I'm a university student, and due to this I don't want to use inheritance since we haven't learned it yet.
class seng305
{
string title = "Software design and architecture", code = "SENG305";
int credit = 4;
public:
seng305();
~seng305();
string get_info();
string get_title();
int get_credit();
};
class comp219
{
string title = "Electronics in computer engineering", code = "COMP219";
int credit = 4;
public:
comp219();
~comp219();
string get_info();
string get_title();
int get_credit();
};
seng305::seng305()
{
cout << '\t' << "Created" << endl;
}
seng305::~seng305()
{
cout << '\t' << "Destroyed" << endl;
}
string seng305::get_info()
{
return (code + "-" + title);
}
string seng305::get_title()
{
return title;
}
int seng305::get_credit()
{
return credit;
}
//--------------------------------------------------
comp219::comp219()
{
cout << '\t' << "Created" << endl;
}
comp219::~comp219()
{
cout << '\t' << "Destroyed" << endl;
}
string comp219::get_info()
{
return (code + "-" + title);
}
string comp219::get_title()
{
return title;
}
int comp219::get_credit()
{
return credit;
}
As you can see, the get_info(), get_title(), and get_credit() methods do the same thing.
I would like for a single get_info(), get_title(), get_credit() to be able to do the task for each class.
There is no reason to use separate classes at all in this example. A single class will suffice, eg:
class course
{
string title, code;
int credit;
public:
course(const string &title, const string &code, int credit);
~course();
string get_info() const;
string get_title() const;
int get_credit() const;
};
course::course(const string &title, const string &code, int credit)
: title(title), code(code), credit(credit)
{
cout << '\t' << "Created" << endl;
}
course::~course()
{
cout << '\t' << "Destroyed" << endl;
}
string course::get_info() const
{
return (code + "-" + title);
}
string course::get_title() const
{
return title;
}
int course::get_credit() const
{
return credit;
}
Then, you simply create instances of your class as needed, eg:
course seng305("Software design and architecture", "SENG305", 4);
course comp219("Electronics in computer engineering", "COMP219", 4);
...
I know you said that you don't want to use inheritance, but that could be the next logical step, using the above code as a base:
class courseSeng305 : public course
{
public:
courseSeng305() : course("Software design and architecture", "SENG305", 4) {}
};
class courseComp219 : public course
{
public:
courseComp219() : course("Electronics in computer engineering", "COMP219", 4) {}
};
courseSeng305 seng305;
courseComp219 comp219;
...

C++ Class variables not printing the right values assigned

I'm trying to create a simple class called 'Game' and assign some values to all three variables. However every time I run it, the values printed at the screen are completely irrelevant, and I'm pretty sure it has to do something with the class constructors but I don't know what exactly.The code is this:
#include <iostream>
#include <string>
using namespace std;
class Game
{
int id;
string name;
string winner;
public:
Game();
Game(int IDvalue, string NAMEvalue );
~Game();
void setId(int IDvalue);
void setName(string NAMEvalue);
void setWinner(string WINNERvalue);
int getId();
string getName();
string getWinner();
void status1();
};
Game::Game()
{
id = 0;
name = " ";
winner = " ";
}
Game::Game(int IDvalue, string NAMEvalue)
{
IDvalue = id;
NAMEvalue = name;
winner = " ";
}
Game::~Game()
{
}
void Game::setId(int IDvalue)
{
IDvalue = id;
}
void Game::setName(string NAMEvalue)
{
NAMEvalue = name;
}
void Game::setWinner(string WINNERvalue)
{
WINNERvalue = winner;
}
int Game::getId()
{
return id;
}
string Game::getName()
{
return name;
}
string Game::getWinner()
{
return winner;
}
void Game::status1()
{
cout << "Game's id : " << id << endl;
cout << "Game's type : " << name << endl;
cout << "Game's winner : " << winner << endl;
}
int main()
{
Game a(1, "Something");
a.setWinner("Someone");
a.status1();
return 0;
}
As you might have noticed (I'm sure you have) I'm pretty new to C++ ,so go easy on me...
Game::Game(int IDvalue, string NAMEvalue)
{
IDvalue = id;
NAMEvalue = name;
winner = " ";
}
Most of these assignments are backwards. To be consistent, the last line should have been
" " = winner;
This constructor isn't initializing id and name; instead it's assigning the (garbage) values of id and name to the parameters IDvalue and NAMEvalue, which are local variables in the function, so they're destroyed when the constructor returns and no one can see their modified values.
Fix:
Game::Game(int IDvalue, string NAMEvalue)
{
id = IDvalue;
name = NAMEvalue;
winner = " ";
}
Or better:
Game::Game(int IDvalue, string NAMEvalue)
: id(IDvalue)
, name(NAMEvalue)
, winner(" ")
{
}
By the way, your setter functions have the same problem.
You are assigning the member variables to the parameters instead of vice versa on the second constructor and set functions.
Game::Game(int IDvalue, string NAMEvalue)
{
IDvalue = id; --> id = IDvalue; OR setID(id);
NAMEvalue = name; --> name = NAMEvalue; OR setName(name);
winner = " ";
}
void Game::setId(int IDvalue)
{
IDvalue = id; --> id = IDvalue;
}
// ... the rest of the set functions

Can someone tell what's wrong with my code?

I am a beginner and just can't figure out what am I doing wrong in this code. The result ends in a infinite loop (I think), that prints nothing. I intentionally left function speak() non-virtual and I know I'll only get Animal's data printed.
#include <iostream>
#include <string>
using namespace std;
class Animal
{
protected:
string m_name;
string m_speak;
public:
Animal(string name, string speak = "???"): m_name(name), m_speak(speak){}
string speak(){cout << m_name << " speaks " << m_speak;}
};
class Dog: public Animal
{
private:
string m_dspeak;
public:
Dog(string name, string speak = "Woof!"): Animal(name), m_dspeak(speak){}
string speak(){cout << m_name << " speaks " << m_dspeak;}
};
class Cat: public Animal
{
private:
string m_cspeak;
public:
Cat(string name, string speak = "Meow!"): Animal(name), m_cspeak(speak){}
string speak(){cout << m_name << " speaks " << m_cspeak;}
};
int main()
{
Cat Fred("Fred");
Dog Stuffy("Stuffy");
Animal *ptr = &Fred;
cout << ptr->speak() << endl;
Animal *ptr2 = &Stuffy;
cout << ptr2->speak() << endl;
}
Can someone help? I may did a very silly mistake here. Please tell me what's wrong?
In your code, you have made two major mistakes.
In the classes Animal, Dog and Cat you have three speak functions. But you declared them as string type functions. But the only output some text but does not return anything. You have to change them to void. Or you can return the text instead of outputing it.
In the main function you have written cout << ptr->speak() << endl; to output the text. But your speak function does not return any string to output. It outputs the text itself. So, you have to write ptr->speak(); to output the speech of the animal. You don't need cout there.
I have given two sample codes below. You can choose either of them. Both works just fine.
Sample #1: using void (no cout in main)
#include <iostream>
#include <string>
using namespace std;
class Animal
{
protected:
string m_name;
string m_speak;
public:
Animal(string name, string speak = "???"): m_name(name), m_speak(speak){}
void speak(){cout << m_name << " speaks " << m_speak;}
};
class Dog: public Animal
{
private:
string m_dspeak;
public:
Dog(string name, string speak = "Woof!"): Animal(name), m_dspeak(speak){}
void speak(){cout << m_name << " speaks " << m_dspeak;}
};
class Cat: public Animal
{
private:
string m_cspeak;
public:
Cat(string name, string speak = "Meow!"): Animal(name), m_cspeak(speak){}
void speak(){cout << m_name << " speaks " << m_cspeak;}
};
int main()
{
Cat Fred("Fred");
Dog Stuffy("Stuffy");
Animal *ptr = &Fred;
ptr->speak();
Animal *ptr2 = &Stuffy;
ptr2->speak();
}
Sample #2: using return in functions and cout in main
#include <iostream>
#include <string>
using namespace std;
class Animal
{
protected:
string m_name;
string m_speak;
public:
Animal(string name, string speak = "???"): m_name(name), m_speak(speak){}
string speak(){return m_name + " speaks " + m_speak;}
};
class Dog: public Animal
{
private:
string m_dspeak;
public:
Dog(string name, string speak = "Woof!"): Animal(name), m_dspeak(speak){}
string speak(){ return m_name + " " + m_speak;}
};
class Cat: public Animal
{
private:
string m_cspeak;
public:
Cat(string name, string speak = "Meow!"): Animal(name), m_cspeak(speak){}
string speak(){ return m_name + " speaks " + m_cspeak;}
};
int main()
{
Cat Fred("Fred");
Dog Stuffy("Stuffy");
Animal *ptr = &Fred;
cout << ptr->speak() << endl;
Animal *ptr2 = &Stuffy;
cout << ptr2->speak() << endl;
}
Change your two implementations of speak() to be something like this:
string speak(){ return m_name + " speaks " + m_speak; }
Currently, your speak methods don't have a return statement, so the return value is undefined, which could cause weird problems.
I am sorry I misunderstood your question. I edited the answer.
You do not need to cout in the function. You would do that in main.
#include <iostream>
#include <string>
using namespace std;
class Animal
{
protected:
string m_name;
string m_speak;
public:
Animal(string name, string speak = "???"): m_name(name), m_speak(speak){}
string speak(){return m_name + " speaks " + m_speak;}
};
class Dog: public Animal
{
private:
string m_dspeak;
public:
Dog(string name, string speak = "Woof!"): Animal(name), m_dspeak(speak){}
string speak(){ return m_name + " " + m_speak;}
};
class Cat: public Animal
{
private:
string m_cspeak;
public:
Cat(string name, string speak = "Meow!"): Animal(name), m_cspeak(speak){}
string speak(){ return m_name + " speaks " + m_cspeak;}
};
int main()
{
Cat Fred("Fred");
Dog Stuffy("Stuffy");
Animal *ptr = &Fred;
cout << ptr->speak() << endl;
Animal *ptr2 = &Stuffy;
cout << ptr2->speak() << endl;
}