I'm working around simple program In MSVS 2010 which is Windows form application, and suddenly reached really weird problem: I can't create virtual functions in class.
Here is the code:
#pragma once;
#include <string>
using namespace std;
using namespace System;
class Reptile
{
private:
char *diet;
string title;
double weight;
int lifespan;
char sex;
public:
char* getDiet();
bool setDiet(char* newDiet);
string getTitle();
bool setTitle(string newTitle);
double getWeight();
bool setWeight(double newWeight);
int getLifespan();
bool setLifeSpan(int newLifespan);
char getSex();
void setSex(char newSex);
virtual void Show(void);
virtual void Voice(void);
~Reptile();
Reptile(); };
It throws error like this:
Reptile.obj : error LNK2028: unresolved token (0A00000E) "public: virtual void __clrcall Reptile::Voice(void)" (?Voice#Reptile##$$FUAMXXZ) referenced in function "void __clrcall dynamic initializer for 'const Reptile::vftable'''(void)" (???__E??_7Reptile##6B###YMXXZ#?A0xc2bc2ccd##$$FYMXXZ)
I really cant figure out how to handle it because I'm not very familiar with clr and stuff.
Include bodies for Show(), Voice(), Reptile() and ~Reptile() and it will work. Like that:
virtual void Show() {};
virtual void Voice() {};
Reptile() {};
~Reptile() {};
Below you can see a working example:
#include <iostream>
#include <string>
using namespace std;
class Reptile
{
private:
char* diet;
string title;
double weight;
int lifespan;
char* sex;
public:
char* getDiet()
{
return diet;
};
void setDiet(char* newDiet)
{
diet = newDiet;
};
string getTitle()
{
return title;
}
void setTitle(string newTitle)
{
title = newTitle;
}
double getWeight()
{
return weight;
}
double setWeight(double newWeight)
{
weight = newWeight;
}
int getLifespan()
{
return lifespan;
}
void setLifeSpan(int newLifespan)
{
lifespan = newLifespan;
}
char* getSex()
{
return sex;
}
void setSex(char* newSex)
{
sex = newSex;
}
// make them pure virtual functions
virtual void Show() = 0;
virtual void Voice() = 0;
Reptile() {};
~Reptile() {};
};
class Dinosaur : public Reptile
{
public:
virtual void Show()
{
cout << "Showing dino" << endl;
}
virtual void Voice()
{
cout << "Rawrrrrr!" << endl;
}
};
int main()
{
Reptile *dino1 = new Dinosaur();
dino1->setSex("M");
dino1->setTitle("T-Rex");
cout << "Type: " << dino1->getTitle() << endl;
cout << "Sex: " << dino1->getSex() << endl;
dino1->Show();
dino1->Voice();
delete dino1;
}
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 written a code like bill payment. Code is working fine but there are many warnings in my code which I want to remove. One of the most frequent warning is deprecated conversion from string constant to 'char* . I have tried many things and some of the warnings are gone but not all. Please anybody point out at my mistakes??
P.S: I have already tried replacing char* to const char* , but then I am not able to exchange or swap values and it was causing error. Any other solution??
Below is the code
#include<iostream>
#include<string.h>
using namespace std;
class item
{
private:
int barcode;
char* item_name;
public:
item (int num=0, char* name="NULL") : barcode(num)
{
item_name=new char[strlen(name)+1];
strcpy(item_name,name);
}
void setbarcode(int num)
{
barcode=num;
}
int getbarcode()
{
return barcode;
}
void scanner()
{
int num;
cin>>num;
setbarcode(num);
}
void printer()
{
cout <<"\nBarcode"<<"\t\t"<<"Item Name"<<"\t\t"<<"Price"<<endl;
cout <<barcode<<"\t\t"<<item_name<<"\t\t\t";
}
~item()
{
delete[]item_name;
}
};
class packedfood : public item
{
private :
int price_per_piece;
public :
packedfood(int a=0, int num=0, char* name = "NULL") : price_per_piece(a),item(num,name)
{
}
void setprice(int num)
{
price_per_piece=num;
}
int getprice()
{
return price_per_piece;
}
void scanner()
{
item::scanner();
}
void printer()
{
item::printer();
cout<<getprice()<<" Per Piece";
}
~packedfood()
{
}
};
class freshfood: public item
{
private:
int price_per_rupee;
float weight;
public:
freshfood(float b=0, int a=0,int num=0,char* name="NULL") : weight(b),price_per_rupee(a),item(num,name)
{
}
void setweight(float b)
{
weight=b;
}
int getweight()
{
return weight*50;
}
void printer()
{
item::printer();
cout<<getweight()<<" Per Rupee"<<endl<<endl;
}
void scanner()
{
item::scanner();
}
~freshfood()
{
}
};
int main()
{
item x(389,"Anything");
item y;
packedfood m(10,118,"Chocolate");
packedfood n;
freshfood r(20.9,93,357,"Fruits");
freshfood s;
cout <<"\n\n Enter the Barcode for Packed food : ";
m.scanner();
m.printer();
cout <<"\n\n Enter the Barcode for Fresh food : ";
r.scanner();
r.printer();
system("PAUSE");
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:
...
}
#include<iostream.h>
#include<conio.h>
using namespace std;
class SpaceShip {};
class GiantSpaceShip : public SpaceShip {};
class Asteroid {
public:
virtual void CollideWith(SpaceShip *) {
cout << "Asteroid hit a SpaceShip" << endl;
}
virtual void CollideWith(GiantSpaceShip *) {
cout << "Asteroid hit a GiantSpaceShip" << endl;
}
};
class ExplodingAsteroid : public Asteroid {
public:
virtual void CollideWith(SpaceShip *) {
cout << "ExplodingAsteroid hit a SpaceShip" << endl;
}
virtual void CollideWith(GiantSpaceShip *) {
cout << "ExplodingAsteroid hit a GiantSpaceShip" << endl;
}
};
int main()
{
SpaceShip * s = new GiantSpaceShip();
Asteroid * a = new ExplodingAsteroid();
a->CollideWith(s);
getch();
return 0;
}
How can I enable double dispatch in C++?
This is not single dispatch but double dispatch: you want the method to depend both on the actual/real type of the object it is invoked on, and on the actual/real type of the argument.
This issue can be solved by the Visitor design pattern.
Luc is right on with using the Visitor pattern, I'm just expanding on that by giving an example of how you could do it.
#include <iostream>
#include <conio.h>
using namespace std;
class SpaceObject;
class SpaceShip;
class GiantSpaceShip;
class Asteroid;
class ExplodingAsteroid;
class SpaceObject {
public:
virtual void CollideWith(SpaceObject*) {}
virtual void CollideWith(SpaceShip*) {}
virtual void CollideWith(GiantSpaceShip*) {}
virtual void CollideWith(Asteroid*) {}
virtual void CollideWith(ExplodingAsteroid*) {}
};
class Asteroid : public SpaceObject {
public:
virtual void CollideWith(SpaceObject* o) { o->CollideWith(this); }
virtual void CollideWith(SpaceShip *) { cout << "Asteroid hit a SpaceShip" << endl; }
virtual void CollideWith(GiantSpaceShip *) { cout << "Asteroid hit a GiantSpaceShip" << endl; }
};
class ExplodingAsteroid : public Asteroid {
public:
virtual void CollideWith(SpaceObject* o) { o->CollideWith(this); }
virtual void CollideWith(SpaceShip *) { cout << "ExplodingAsteroid hit a SpaceShip" << endl; }
virtual void CollideWith(GiantSpaceShip *) { cout << "ExplodingAsteroid hit a GiantSpaceShip" << endl; }
};
class SpaceShip : public SpaceObject {
public:
virtual void CollideWith(SpaceObject* o) { o->CollideWith(this); }
virtual void CollideWith(Asteroid* o) { o->Asteroid::CollideWith(this); }
virtual void CollideWith(ExplodingAsteroid* o) { o->ExplodingAsteroid::CollideWith(this); }
};
class GiantSpaceShip : public SpaceShip {
public:
virtual void CollideWith(SpaceObject* o) { o->CollideWith(this); }
virtual void CollideWith(Asteroid* o) { o->Asteroid::CollideWith(this); }
virtual void CollideWith(ExplodingAsteroid* o) { o->ExplodingAsteroid::CollideWith(this); }
};
int main()
{
SpaceObject* s = new GiantSpaceShip();
SpaceObject* a = new ExplodingAsteroid();
a->CollideWith(s);
getch();
return 0;
}