I've been trying to figure out how to add a private member from Object A, to a private member from Object B.
Both Cat and Dog Class's inheriate from the base class Animal. I have a thrid class 'MyClass', that I want to inheriate the private members of the Cat and Dog class. So in MyClass, I have a friend function to overload the + operator. THe friend function is defined as follows:
MyClass operator+(const Dog &dObj, const Cat &cObj);
I want to access dObj.age and cObj.age within the above function, invoke by this statement in main:
mObj = dObj + cObj;
Here is the entire source for a complete reference into the class objects:
#include <iostream>
#include <vld.h>
using namespace std;
class Animal
{
public :
Animal() {};
virtual void eat() = 0 {};
virtual void walk() = 0 {};
};
class Dog : public Animal
{
public :
Dog(const char * name, const char * gender, int age);
Dog() : name(NULL), gender(NULL), age(0) {};
virtual ~Dog();
void eat();
void bark();
void walk();
private :
char * name;
char * gender;
int age;
};
class Cat : public Animal
{
public :
Cat(const char * name, const char * gender, int age);
Cat() : name(NULL), gender(NULL), age(0) {};
virtual ~Cat();
void eat();
void meow();
void walk();
private :
char * name;
char * gender;
int age;
};
class MyClass : private Cat, private Dog
{
public :
MyClass() : action(NULL) {};
void setInstance(Animal &newInstance);
void doSomething();
friend MyClass operator+(const Dog &dObj, const Cat &cObj);
private :
Animal * action;
};
Cat::Cat(const char * name, const char * gender, int age) :
name(new char[strlen(name)+1]), gender(new char[strlen(gender)+1]), age(age)
{
if (name)
{
size_t length = strlen(name) +1;
strcpy_s(this->name, length, name);
}
else name = NULL;
if (gender)
{
size_t length = strlen(gender) +1;
strcpy_s(this->gender, length, gender);
}
else gender = NULL;
if (age)
{
this->age = age;
}
}
Cat::~Cat()
{
delete name;
delete gender;
age = 0;
}
void Cat::walk()
{
cout << name << " is walking now.. " << endl;
}
void Cat::eat()
{
cout << name << " is eating now.. " << endl;
}
void Cat::meow()
{
cout << name << " says meow.. " << endl;
}
Dog::Dog(const char * name, const char * gender, int age) :
name(new char[strlen(name)+1]), gender(new char[strlen(gender)+1]), age(age)
{
if (name)
{
size_t length = strlen(name) +1;
strcpy_s(this->name, length, name);
}
else name = NULL;
if (gender)
{
size_t length = strlen(gender) +1;
strcpy_s(this->gender, length, gender);
}
else gender = NULL;
if (age)
{
this->age = age;
}
}
Dog::~Dog()
{
delete name;
delete gender;
age = 0;
}
void Dog::eat()
{
cout << name << " is eating now.. " << endl;
}
void Dog::bark()
{
cout << name << " says woof.. " << endl;
}
void Dog::walk()
{
cout << name << " is walking now.." << endl;
}
void MyClass::setInstance(Animal &newInstance)
{
action = &newInstance;
}
void MyClass::doSomething()
{
action->walk();
action->eat();
}
MyClass operator+(const Dog &dObj, const Cat &cObj)
{
MyClass A;
//dObj.age;
//cObj.age;
return A;
}
int main()
{
MyClass mObj;
Dog dObj("B", "Male", 4);
Cat cObj("C", "Female", 5);
mObj.setInstance(dObj); // set the instance specific to the object.
mObj.doSomething(); // something happens based on which object is passed in
dObj.bark();
mObj.setInstance(cObj);
mObj.doSomething();
cObj.meow();
mObj = dObj + cObj;
return 0;
}
If you want to access a private member of Dog, then your operator has to be a friend of Dog, not just a friend of some derived class of Dog.
If you add friend MyClass operator+(const Dog &dObj, const Cat &cObj); to the definition of class Cat and class Dog, then the function will have access to dObj.age and cObj.age.
Alternatively, you could add friend MyClass; to the definitions of class Cat and class Dog, but then all of MyClass's functions have access to all of Cat and Dog's internals.
Alternatively alternatively, you could make age protected rather than private.
Related
I have following Classes:
class Vehicle
{
public:
Vehicle(int id);
virtual int getID() const;
virtual void setCustom(Customer* custom);
virtual Customer *getCustom() const;
virtual void printOnce() const = 0;
protected:
int id_;
Customer* custom_;
};
Vehicle::Vehicle(int id)
: id_{id}, custom_{nullptr}
{
}
class Car : public Vehicle
{
public:
Car(int id, int seats, string color);
virtual void printOnce() const override;
private:
int seats_;
int color_;
};
Car::Car(int id, int seats, string color)
: Vehicle(id), seats_{seats}, color_{color}
{
}
class Customer
{
public:
Customer(string customerName, int age, int driverlicenceType);
string getCustomerName() const;
private:
string customerName_;
int age_;
int driverlicenceType_;
};
Customer::Customer(string customerName, int age, int driverlicenceType)
: customerName_{customerName}, age_{age}, driverlicenceType_{driverlicenceType}
{
}
string Customer::getCustomerName() const
{
return customerName_;
}
and the following Method:
Vehicle *CarRental::findByName(string name)
{
auto cmp =[name](Vehicle* v){
if(v->getCustom() != nullptr) {
return name == v->getCustom()->getCustomerName();
}
};
//find Vehicle in vector <Vehicle*> vehicles_;
return (*find_if(vehicles_.begin(), vehicles_.end(), cmp));
}
Now I'm trying to get the Vehicle*, cast it to Car*, and test if the Customer is nullptr.
Code:
Vehicle* veh = findByName(name);
Car* c = dynamic_cast<Car*>(veh);
if(c->getCustom() == nullptr) {
//do anything
}
But somehow it isn't nullptr. If I try to get the name or age:
cout << "Customer: " << c->getCustom() << endl;
it shows me only Customer: (like an empty string). I think if it were nullptr this should not work and give me an error but I don't know why.
In my function 'func' i want to create an object Menu who returns a breakfast with lemon and coffee. 'func' return a list of menu
When I try to display the menu for a breakfast that contains only lemon or only coffee it is displayed correctly. For example:
c.push_back(make_unique<Breakfast>("eggs", 10));
but when i try to display a menu that also contains lemon and coffee it shows me error in main
this is the program:
#include <iostream>
#include <vector>
using namespace std;
class Menu {
private:
int price;
public:
Menu(int p = 0) : price{ p } {}
virtual string description() = 0;
virtual int getPrice() {
return price;
}
virtual ~Menu() {}
};
class WithLemon : public Menu {
private:
Menu* meniu;
public:
WithLemon(Menu* n) :
meniu{ n } {}
string description() override {
return meniu->description() + " with lemon ";
}
int getPrice() override {
return meniu->getPrice() + 4;
}
};
class WithCoffee : public Menu {
private:
Menu* meniu;
public:
WithCoffee(Menu* n) :
meniu{ n } {
}
string description() override {
return meniu->description() + " with coffee ";
}
int getPrice() override {
return meniu->getPrice() + 5;
}
};
class Breakfast : public Menu {
private:
string name;
public:
Breakfast(string n, int p) :
name{ n }, Menu{ p } {
}
string description() override {
return name;
}
};
std::vector<std::unique_ptr<Menu>> func(void)
{
std::vector <std::unique_ptr<Menu> > c;
Breakfast a{ "breakfast eggs", 10 };
WithCoffee breakfast_with_coffee{ &a };
Menu* breakfast_with_coffee_and_lemon = new WithLemon{ &breakfast_with_coffee };
//cout << breakfast_with_coffee_and_lemon->description() << " " << breakfast_with_coffee_and_lemon->getPrice();// print ----> breakfast eggs with coffee with lemon 19
c.push_back(make_unique<WithLemon>(&breakfast_with_coffee));
return c;
}
int main() {
std::vector < std::unique_ptr<Menu> > lista = func();
for (int i = 0; i < lista.size(); i++) {
cout << lista[i]->description() << " " << lista[i]->getPrice() << endl; //error read memory access
}
return 0;
}
You can't take a pointer to automatic memory, store it in a smart pointer and leave the function. After you leave the function the automatic memory is freed and the smart pointer contains a dangling pointer. The simplest way to avoid this problem and other problems with memory leaks is to use smart pointers for all variables:
#include <iostream>
#include <memory>
#include <string>
#include <vector>
class Menu {
private:
int price;
public:
Menu(int p = 0) : price{ p } {}
virtual std::string description() = 0;
virtual int getPrice() {
return price;
}
virtual ~Menu() = default;
};
class WithLemon : public Menu {
private:
std::unique_ptr<Menu> meniu;
public:
WithLemon(Menu* n) : meniu{ n } {}
std::string description() override {
return meniu->description() + " with lemon ";
}
int getPrice() override {
return meniu->getPrice() + 4;
}
};
class WithCoffee : public Menu {
private:
std::unique_ptr<Menu> meniu;
public:
WithCoffee(Menu* n) :
meniu{ n } {
}
std::string description() override {
return meniu->description() + " with coffee ";
}
int getPrice() override {
return meniu->getPrice() + 5;
}
};
class Breakfast : public Menu {
private:
std::string name;
public:
Breakfast(std::string n, int p) : Menu{ p }, name{ n } {}
std::string description() override {
return name;
}
};
std::vector<std::unique_ptr<Menu>> func(void) {
std::vector <std::unique_ptr<Menu> > c;
auto a = std::make_unique<Breakfast>("breakfast eggs", 10);
auto breakfast_with_coffee = std::make_unique<WithCoffee>(a.release());
//Menu* breakfast_with_coffee_and_lemon = new WithLemon{ breakfast_with_coffee };
//std::cout << breakfast_with_coffee_and_lemon->description() << " " << breakfast_with_coffee_and_lemon->getPrice();// print ----> breakfast eggs with coffee with lemon 19
c.push_back(std::make_unique<WithLemon>(breakfast_with_coffee.release()));
return c;
}
int main() {
std::vector < std::unique_ptr<Menu> > lista = func();
for (const auto &i : lista) {
std::cout << i->description() << " " << i->getPrice() << std::endl; //error read memory access
}
return 0;
}
Avoid raw new and delete. Avoid pointers to automatic memory.
I have a base Class named Animals and 2 derived class Dog and Cat
class Animal{
protected:
std::string name;
std::string color;
public:
std::string getName() {
return name;
}
std::string getColor() {
return color;
}
...
class Cat : public Animal {
private :
int lives;
public :
int getLives() {
return lives;
}
...
class Dog : public Animal {
private :
std::string gender;
public:
std::string getGender(){
return gender;
}
...
and i have e vec of shared_ptr
std::vector<std::shared_ptr<Animal>> animals
I've added some cats and dogs in the vector and i am trying to print all the characteristics of each animal from vector ,using operator >>(this is a homework,we have to use this ) and i did this
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<std::shared_ptr<T>>& v)
{
for (int i = 0; i < v.size(); ++i) {
os << v[i]->getName();
os << "-";
os << v[i]->getColor();
if (i != v.size() - 1)
os << ", ";
os<<"\n";
}
return os;
}
but in this way i can print only the name and color or the animals(these atributes are in the base class)
My question is :
How can i print all the attributes ,for cats lives and for dogs gender???
Try this:
class Animal {
protected:
std::string name;
std::string color;
public:
virtual void print(std::ostream& os){
os << "Name:" << name <<" Color:"<< color;
}
void setName(string n) { name = n; }
void setColor(string c) { color = c; }
std::string getName() {
return name;
}
std::string getColor() {
return color;
}
};
class Cat : public Animal {
private:
int lives;
public:
void setLives(int n) { lives = n; }
void print(std::ostream& os) {
Animal::print(os);
os <<" Lives:"<<lives;
}
int getLives() {
return lives;
}
};
class Dog : public Animal {
private:
std::string gender;
public:
void setGender(string g) { gender = g; }
void print(std::ostream& os) {
Animal::print(os);
os << " Gender:" << gender;
}
std::string getGender() {
return gender;
}
};
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<std::shared_ptr<T>>& v)
{
for (int i = 0; i < v.size(); ++i) {
v[i]->print(os);
os << "\n";
}
return os;
}
int main()
{
shared_ptr<Dog> d1 = make_shared<Dog>();
d1->setName("Dog1"); d1->setColor("White"); d1->setGender("Male");
shared_ptr<Cat> c1 = make_shared<Cat>();
c1->setName("Cat1"); c1->setColor("Brown"); c1->setLives(1);
vector<shared_ptr<Animal>> vec;
vec.push_back(d1);
vec.push_back(c1);
cout << vec;
return 0;
}
class People {
public:
People(string name);
void setName(string name);
string getName();
void setAge(int age);
int getAge();
virtual void do_work(int x);
void setScore(double score);
double getScore();
protected:
string name;
int age;
double score;
};
class Student: public People {
public:
Student(string name);
virtual void do_work(int x);
};
class Instructor: public People {
public:
Instructor(string name);
virtual void do_work(int x);
};
People::People(string name) {
this->name = name;
this->age = rand()%100;
}
void People::setName(string name) {
this->name = name;
}
string People::getName() {
return this->name;
}
void People::setAge(int age) {
this->age = age;
}
int People::getAge() {
return this->age;
}
void People::setScore(double score) {
this->score = score;
}
double People::getScore() {
return this->score;
}
void People::do_work(int x) {
}
Student::Student(string name):People(name){
this->score = 4 * ( (double)rand() / (double)RAND_MAX );
}
void Student::do_work(int x) {
srand(x);
int hours = rand()%13;
cout << getName() << " did " << hours << " hours of homework" << endl;
}
Instructor::Instructor(string name): People(name) {
this->score = 5 * ( (double)rand() / (double)RAND_MAX );
}
void Instructor::do_work(int x) {
srand(x);
int hours = rand()%13;
cout << "Instructor " << getName() << " graded papers for " << hours << " hours " << endl;
}
int main() {
Student student1("Don");
Instructor instructor1("Mike");
People t(student1);
t.do_work(2);
}
Why the do_work class is not getting overridden ? There is a people class and the Instructor and Student class are inheriting those classes. There is a virtual method in People class, which is implemented in Student and Instructor. But it is not getting overridden ? Thanks in advance !
You need to have pointers or references to objects to make overriding work:
Student* student1 = new Student("Don");
Instructor* instructor1 = new Instructor("Mike");
People* t = student1;
t->do_work(2);
And please don't forget to delete your allocated memory:
delete student1;
delete instructor1;
That would be just enough to make it work, but for the sake of safety and avoiding memory leaks, you can just go:
#include <memory>
...
int main() {
auto student1 = std::make_unique<Student>("Don");
auto instructor1 = std::make_unique<Instructor>("Mike");
People* t = student1.get();
t->do_work(2);
}
Also please consider declaring a virtual destructor in your base class, that would be a must if you inherit from People and add a member field in the inherited class:
class People {
public:
...
virtual ~People() {}
protected:
...
}
I am fairly new to C++ and I am wanting to understand why my program is giving me this error. I constructing a program that will simulate a colony of bunnies. Being able to automatically add them, give them names, ages, etc.
These are the errors that I am getting:
main2.cpp: In function ‘int main()’:
main2.cpp:109:6: error: ‘void Bunny::printBunny()’ is private
void printBunny()
^
main2.cpp:132:26: error: within this context
colony[ i ].printBunny();
^
Here is the code that I have come up with.
enter code here
#include <iostream>
#include <string>
#include <ctime>
#include <vector>
#include <cstdlib>
using namespace std;
void setSex( void );
char getSex();
void setColor( void );
string getColor();
void setAge( void );
int getAge();
void setName( void );
string getName();
void printBunny();
static const int POSSIBLE_NAMES = 5;
static const int POSSIBLE_COLORS = 4;
class Bunny
{
char sex;
string color;
int age;
string name;
bool radioactive_mutant_vampire_bunny;
BunnyData()
{
//srand( time( 0 ) );
setSex();
setColor();
setAge();
setName();
}
void setSex()
{
int randomNumber = 1 + rand() % 2;
( randomNumber == 1 ) ? sex = 'm' : sex = 'f';
}
char getSex()
{
return sex;
}
void setColor()
{
//color = possibleColors[ 0 + rand() % POSSIBLE_COLORS ];
}
string getColor()
{
return color;
}
void setAge()
{
age = 0;
}
int getAge()
{
return age;
}
void setName()
{
//name = possibleNames[ 0 + rand() % POSSIBLE_NAMES ];
}
string getName()
{
return name;
}
void printBunny()
{
cout << "Name: " << getName() << endl;
cout << "Sex: " << getSex() << endl;
cout << "Color: " << getColor() << endl;
cout << "Age: " << getAge() << endl;
}
};
int main()
{
vector< Bunny > colony;
cout << "Welcome to Bunny Graduation!" << endl << endl;
for( int i = 0; i < 5; ++i )
{
colony.push_back( Bunny() );
}
for( int i = 0; i < 5; ++i )
{
colony[ i ].printBunny();
cout << endl;
}
return 0;
}
Everything in a class has private access unless stated otherwise For example,
class access
{
int iAmPrivate; // private. Not accessible outside of the class
public:
int getValue() //public and accessible to all
{
return iAmPrivate;
}
int iAmPublic; //also public
}
Documentation on access levels.
You need to declare them to be public, if you don't, these members are private by default, which means you cannot invoke them outside the class.
class Bunny
{public:
void printBunny() {...}
};
You really need to consider which class access modifier you should apply to the member, because normally, we don't use just one type of access modifier in OO.
You can check this site to learn more about it.
In your class:
class Bunny
{
char sex;
string color;
int age;
string name;
// Rest of class fields ...
}
All the fields are private by default. This is because you have not used the keyword public: before you declare the fields of the class Bunny. As a result, you cannot invoke/call these fields and functions outside of the class, as you have tried in:
colony[ i ].printBunny(); // you are calling a private member of class Bunny outside of the class
There are 2 ways to get around this error:
One way is that you can declare the class members as public. This will allow the functions and fields to be invoked outside of the class:
class Bunny
{
public: // declare all fields of the class as public
char sex;
string color;
int age;
string name;
// Rest of class fields ...
}
Another thing you can do is declare Bunny as a struct instead if a class. This way, all your fields sill be accessible outside the struct:
struct Bunny
{
char sex;
string color;
int age;
string name;
// Rest of class fields ...
}