I am new to OOP and I have encountered a problem while writing my first code. I do not understand why I can not use one class as a part of another. And no I do not want that class to inherit another. One of the requirements is that I prevent object copying.
#pragma once
#include<iostream>
#include<string>
using namespace std;
class Pilot
{
public:
Pilot(/*string x*/)
{
setName();
flight_hours = 0;
set_status(0);
}
void setName(/*string x*/)
{
cout<<"Unesi ime pilota: ";
getline(cin,name);
}
string getName()
{
return name;
}
void increase_flight_hours(int n)
{
flight_hours += n;
}
int get_flight_hours()
{
return flight_hours;
}
void set_status(bool b)
{
status;
}
bool get_status()
{
return status;
}
void display_pilot()
{
cout << name;
cout << "(", flight_hours, ")";
if (status)
cout << "-L" << endl;
else
cout << "-N" << endl;
}
Pilot (const Pilot&) = delete;
void operator=(const Pilot&) = delete;
private:
string name;
int flight_hours;
bool status;
};
#pragma once
#include"Pilot.h"
class Avion
{
public:
Avion ()
{
setName();
set_capacity();
}
void setName(/*string x*/)
{
cout << "Unesi ime aviona: ";
getline(cin, name);
}
string getName()
{
return name;
}
void set_capacity()
{
cout << "Unesite kapacitet aviona: ";
cin >> capacity;
}
int get_capacity()
{
return capacity;
}
Pilot get_captain()
{
return captain;
}
private:
string name;
Pilot captain;
Pilot copilot;
int capacity;
};
I get this error :
function "Pilot::Pilot(const Pilot &)" (declared at line 50 of "C:\Users\mjova\source\repos\Project1\Project1\Pilot.h") cannot be referenced -- it is a deleted function Project1 C:\Users\mjova\source\repos\Project1\Project1\Planes.h 36
One problem is here:
Pilot get_captain()
{
return captain;
}
which returns a copy of the captain, and you have expressly disallowed copying.
Return a const reference instead:
const Pilot& get_captain()
{
return captain;
}
(and don't try to copy what it returns).
There could also be some other copying-related code in "Planes.h"; it's not clear whether Avion is defined in that file or not.
Side note: since you can't copy Pilots, the captain and copilot members of Avion are problematic (you can't implement set_captain, for instance).
I suspect that you're going to want to change them to be pointers in the future, and let pilots exist without planes and vice versa.
Related
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.
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.
A class BookLibrary constructs a vector of objects of class BookInfo. The task is to add some 'books' (objects of class BookInfo) into the vector and print them out. For some reason, a conventional for(unsigned int i = 0; i < vector.size(); i++) cout << vector[i] << endl; loop is not working. This is a homework project from Savitch textbook "Problem Solving with C++".
Here's the code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class BookInfo
{
public:
BookInfo(string newAuthor, string newTitle);
BookInfo(string newTitle);
string getName();
string getAuthor();
string getTitle();
private:
string author;
string title;
};
class BookLibrary
{
public:
BookLibrary();
BookLibrary(vector<BookInfo> newLibrary);
void add(BookInfo newBook);
void size();
void printInfo();
private:
vector<BookInfo> library;
};
int main()
{
BookLibrary library1;
BookInfo book1("Michael Krichton", "Jurassic Park");
BookInfo book2("War and Peace"), book3("Valter Savitch", "Programming in C++");
library1.add(book1);
library1.add(book2);
library1.add(book3);
library1.size();
library1.printInfo();
return 0;
}
BookInfo::BookInfo(string newAuthor, string newTitle)
{
author = newAuthor;
title = newTitle;
}
BookInfo::BookInfo(string newTitle) :
title(newTitle), author("unknown")
{}
string BookInfo::getName()
{
return (author + " " + title);
}
string BookInfo::getAuthor()
{
return author;
}
string BookInfo::getTitle()
{
return title;
}
BookLibrary::BookLibrary()
{}
BookLibrary::BookLibrary(vector<BookInfo> newLibrary)
{
library = newLibrary;
}
void BookLibrary::add(BookInfo newBook)
{
library.push_back(newBook);
}
void BookLibrary::size()
{
cout << library.size();
}
void BookLibrary::printInfo()
{
for (unsigned int i = 0; i < library.size(); i++)
cout << library[i] << endl;
}
It underlines the cout << in the last line.
Your loop is not able to print out a BookInfo object, because you have not defined an operator<< for BookInfo. As such, a statement like cout << library[i] does not know what to do with the BookInfo that library[i] returns.
You need to add that operator, eg:
class BookInfo
{
public:
...
friend ostream& operator<<(ostream &os, const BookInfo &book)
{
os << "\"" << book.title << "\" by " << book.author;
return os;
}
...
};
If you want to use your getName() method instead, you would need to declare it as const (which you should do anyway for all of your getters), eg:
class BookInfo
{
public:
...
string getName() const;
...
friend ostream& operator<<(ostream &os, const BookInfo &book)
{
os << book.getName();
return os;
}
...
};
string BookInfo::getName() const
{
return ...;
}
Not sure where I am at the moment, trying to figure it out. I need to initialize the members in print() const as it is giving me random gibberish. No matter what I try to do, it does not seem to work. Not sure what to even do. Can anyone give me a hand?
*edit: Added in the rest of the code. Forgot it when I submitted the first time.
Student.cpp
#include "student.h"
//implement the required 3 functions here
Student::Student(const char initId[], double gpa)
{
// initialize a newly created student object with the passed in value
}
bool Student::isLessThanByID(const Student& aStudent) const
{
// compare the current student object with the passed in one by id.
if (strcmp(id, aStudent.id) > 0)
{
return true;
}
else
{
return false;
}
}
bool Student::isLessThanByGpa(const Student& aStudent) const
{
// compare the current student object with the passed in one by gpa
if (gpa < aStudent.gpa)
{
return true;
}
else
{
return false;
}
}
void Student::print() const
{
cout << id << '\t' << gpa << endl;
}
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
using namespace std;
class Student
{
public:
Student(const char initId[], double gpa);
bool isLessThanByID(const Student& aStudent) const;
bool isLessThanByGpa(const Student& aStudent) const;
void print()const;
private:
const static int MAX_CHAR = 100;
char id[MAX_CHAR];
double gpa;
};
#endif
app.cpp
#include "student.h"
int main()
{
Student s1("G10", 3.9);
Student s2("G20", 3.5);
s1.print();
s2.print();
if(s1.isLessThanByID(s2))
{
cout << "about right!" << endl;
}
else
{
cout << "uhmm ..." << endl;
}
if(!s1.isLessThanByGpa(s2))
{
cout << "about right!" << endl;
}
else
{
cout << "uhmm ..." << endl;
}
system("pause");
return 0;
}
There is nothing in that code that sets the values of Student::id and Student::gpa. Your constructor has parameters initId and gpa; you should copy those into your object. Based on the declaration of Student that you provided, something this should be appropriate:
Student::Student(const char initId[], double gpa) : gpa(gpa)
{
strncpy(id, initId, Student::MAX_CHAR-1);
id[Student::MAX_CHAR-1] = '\0';
}
My task is as follows :
Using pointers to class fields, create menu allowing selection of ice, that Person can buy in Ice shop. Buyer will be charged with waffel and ice costs.
Selection of ice and charging buyers account must be shown in program.
Here's my Person class :
#include <iostream>
using namespace std;
class Iceshop {
const double waffel_price = 1;
public:
}
class Person {
static int NUMBER;
char* name;
int age;
const int number;
double plus, minus;
public:
class Account {
int number;
double resources;
public:
Account(int number, double resources)
: number(number), resources(resources)
{}
}
Person(const char* n, int age)
: name(strcpy(new char[strlen(n)+1],n)),
number(++NUMBER), plus(0), minus(0), age(age)
{}
Person::~Person(){
cout << "Destroying resources" << endl;
delete [] name;
}
friend void show(Person &p);
int* take_age(){
return &age;
}
char* take_name(){
return name;
}
void init(char* n, int a) {
name = n;
age = a;
}
Person& remittance(double d) { plus += d; return *this; }
Person& paycheck(double d) { minus += d; return *this; }
Account* getAccount();
};
int Person::
Person::Account* Person::getAccount() {
return new Account(number, plus - minus);
}
void Person::Account::remittance(double d){
resources = resources + d;
}
void Person::Account::paycheck(double d){
resources = resources - d;
}
void show(Person *p){
cout << "Name: " << p->take_name() << "," << "age: " << p->take_age() << endl;
}
int main(void) {
Person *p = new Person;
p->init("Mary", 25);
show(p);
p->remittance(100);
system("PAUSE");
return 0;
}
How to change this into using pointers to fields ?
class Iceshop {
const double waffel_price;
int menu_options;
double[] menu_prices;
char* menu_names;
char* name;
public:
IceShop(char*c)
: name(strcpy(new char[strlen(n)+1],n)),
waffel_price(1), menu(0)
{}
void init(int[] n){
menu_options = n;
}
void showMenu(Iceshop &i){
int list;
list = &i
char* sorts = i->menu_names;
int count=0;
while(count < list){
cout << count+1 << ")" << sorts[count] << endl;
++count;
}
}
void createMenu(Iceshop *i){
for(int j=0; j <(i->menu_options), ++j){
cout << "Ice name: ";
cin >> i->menu_names[j];
endl;
cout << "Ice cost: "
cin >> i->menu_prices[j];
endl;
}
}
void chargeClient(Person *p, Iceshop* i, int sel){
p->remittance( (i->menu_prices[sel])+(i->waffel_price) );
}
};
You could try to build a menu driven UI.
Something like this (copy paste from a forum, for more examples search for 'C++ console' menu' or something like it on google.
int choice = 0;
while (choice != 4)
{
cout <<"Enter choice:"<< endl <<
"1) ice 1" << endl <<
"2) ice 2" << endl<<
"3) ice 3" << endl <<
"4) exit" << endl;
cin >> choice;
switch(choice)
{
case 1:
//show menu to buy or cancel
break;
case 2:
//show menu to buy or cancel
break;
}
//etc
}
Here is what I would do. Note that it's not exactly what you're looking for and, well, abstract situation modelling is always tough :)
But I hope this code would make you understand what you have to do.
Also, I am not exactly sure about using pointers to class fields, because this tends to be a situation where pointer usage is superflous.
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
// Some abstract type used to measure prices
typedef size_t money_t;
struct Item {
// Item's name and price
std::string name;
money_t price;
// Could also have something that makes
// it an item, but this is not necessary
// This could be anything, because we're actually
// modelling an abstract situation
// (...)
// Note that we don't allow unnamed items
Item(const std::string& name, const money_t& price = 0) : name(name), price(price) { }
// Note here that items are treated as 'same' only by names
// This means we're actually talking about 'logical groups' of items
bool operator==(const Item& item) const { return name == item.name; }
bool operator==(const std::string& item_name) const { return name == item_name; }
};
class Store {
private:
// Store's item storage
// Note that items actually represent infinite groups
// of items (in our case store is an abstract store
// which items simply can't end)
std::vector<Item> items;
public:
// Initialize a store that doesn't sell anything
Store() { }
// Initialize a store that could sell specified types of items
Store(const std::vector<Item>& items) : items(items) { }
// Show what we actually sell in this store
void EnumerateItems() const {
for (size_t i = 0; i < items.size(); ++i)
std::cout << items[i].name << " : " << items[i].price << "\n";
}
Item Sell(const std::string& name) const {
// Find appropriate item in the item list
std::vector<Item>::const_iterator what = std::find(items.begin(), items.end(), name);
// If nothing found, throw an exception
if (what == items.end()) {
throw std::domain_error("Store doesn't sell this type of item");
}
// Return item as a sold one
return (*what);
}
};
class Person {
private:
// Person's name (identity)
std::string name;
// Item's that are currently possesed
// by this person
std::vector<Item> owned_items;
// Amount of cash that this person has
money_t cash;
public:
// Note that we don't allow unnamed persons
Person(const std::string& name, const money_t& cash = 0) : name(name), cash(cash) { }
void Buy(const Item& what) {
owned_items.push_back(what);
cash -= what.price;
}
};
void GoShopping(Person& person, const Store& store) {
// Let's simulate buying one item
// You could easily make a loop and determine what to buy in
// every loop iteration
store.EnumerateItems();
person.Buy(store.Sell("Shoes"));
}
int main() {
// Initialize our store that sells only shoes
std::vector<Item> items;
items.push_back(Item("Shoes", 25));
Store grocery(items);
// Initialize our person
Person jim_carrey("Jim Carrey", 500);
// The yummy part
GoShopping(jim_carrey, grocery);
return 0;
}