Overriden virtual method not being called - c++

In the below code, I am trying to override the price() function for both Taxed and Untaxed, however, they both call the parent virtual function instead of the overriden one that was given to them. What did I mess up?
Header file:
#ifndef PRODUCT_H
#define PRODUCT_H
#include <string>
#include <iostream>
class Product {
protected:
int _quantity;
double _cost;
std::string _name;
public:
Product(std::string name, double cost);
virtual ~Product();
void set_quantity(int quantity);
virtual double price() const;
friend std::ostream & operator<< (std::ostream &ost, const Product &product);
};
std::ostream & operator<< (std::ostream &ost, const Product &product);
class Taxed : public Product{
private:
static double _tax;
public:
using Product::Product;
virtual ~Taxed();
static void set_tax_rate(double sales_tax);
double price() const override;
};
class Taxfree : public Product{
public:
using Product::Product;
virtual ~Taxfree();
double price() const override;
};
#endif //PRODUCT_H
.cpp file:
#include <string>
#include <iomanip>
#include <iostream>
#include "product.h"
Product::Product(std::string name, double cost){
_name = name;
_cost = cost;
_quantity = NULL;
};
Product::~Product(){};
void Product::set_quantity(int quantity){
if (quantity < 0){
std::cerr << "Cannot have negative quantity";
}
_quantity = quantity;
};
double Product::price() const {
return 2;
};
std::ostream & operator<< (std::ostream &ost, const Product &product){
if (product._quantity > 0)
ost << product._name << " (" << product._quantity << " # " << std::fixed << std::setprecision(2) << std::setfill('0') << product.price() << ")";
else
ost << product._name << " (" << std::fixed << std::setprecision(2) << std::setfill('0') << product.price() << ")";
return ost;
};
double Taxed::_tax = 0.0825;
Taxed::~Taxed(){};
void Taxed::set_tax_rate(double sales_tax) {
Taxed::_tax = sales_tax;
};
double Taxed::price() const{
return _quantity * _cost * (1+_tax);
}
Taxfree::~Taxfree(){};
double Taxfree::price() const{
return _quantity * _cost;
}

You are experiencing object slicing. By storing a std::vector<Product>, you are actually creating instances of the base Product class and losing your instances of Taxed and Taxfree. In products.push_back(Taxfree("Apple", 2)), the Taxfree is passed to the compiler-generated copy constructor Product(const Product&), because a Taxfree object can bind to a const Product&.
Had you removed the base implementation of price() and made it a pure virtual function with virtual double price() const = 0;, you would have noticed this problem when your program failed to compile (because Product would become an abstract class and constructing it would no longer be possible).
Instead, you will need to use something like std::vector<std::shared_ptr<Product>>:
std::vector<std::shared_ptr<Product>> products;
products.push_back(std::make_shared<Taxfree>("Apple", 2));
products.push_back(std::make_shared<Taxed>("Iron",1.75));
products.push_back(std::make_shared<Taxfree>("Soda",2.5));
products.push_back(std::make_shared<Taxfree>("Lemon",2.5));
(I'd suggest unique_ptr instead, but it looks like you want the products and cart to contain the same object. Or, you could use unique_ptr and just create copies of the products, which is probably better if you plan to mutate them.)

Related

How to display an array of objects derived from a base class, each with it's own different operator overload function?

So i have a base class, and 3 derived classes, and another class template which as a parameter is given the base class, class template has an array of the 3 different type of objects. I have overloaded the << operator for all 3 derived classes and the base class, but when i try to display all the array in the console, the base class operator overload function is used, how do i make it in such a way that when i iterate through the array of objects and display each one, it's different for every type of object?
base class representation
#pragma once
#include <iostream>
#include <string>
class Sushi
{
private:
static int count;
protected:
int id;
int cost;
std::string fish_type;
public:
Sushi();
Sushi(int cost, std::string fish_type);
~Sushi();
int get_id();
int get_cost();
std::string get_ftype();
void set_cost(int cost);
void set_ftype(std::string fish);
friend std::ostream& operator<<(std::ostream& os, const Sushi& sushi);
};
base class operator
std::ostream& operator<<(std::ostream& os, const Sushi& sushi)
{
os << sushi.id << " " << sushi.cost << " " << sushi.fish_type << std::endl;
return os;
}
class template representation
#pragma once
#include "Sushi.h"
template <class Sushi>
class SushiRepository
{
Sushi *repo;
int capacity;
int top;
public:
//default constructor
SushiRepository();
//constructor
SushiRepository(int size);
//adds an element to top of the stack
void push(Sushi s);
//Pops an element from the top of the stack and returns it
Sushi pop();
//Returns the last element from the top of the stack
Sushi peek();
//returns the size of the repo
int size();
//checks if repo is empty
bool isEmpty();
//checks if repo is full
bool isFull();
//remove by id
void removeByID(int id);
//display all
void displayAll();
~SushiRepository();
};
class template display function
template <class Sushi>
inline void SushiRepository<Sushi>::displayAll()
{
if (!isEmpty()) {
for (int i = 0; i < size(); i++)
{
std::cout << repo[i] << std::endl;
}
}
else {
std::cout << "Repo is empty";
}
}
template<class Sushi>
SushiRepository<Sushi>::~SushiRepository()
{
delete[] repo;
}
derived class representation
#pragma once
#include "Sushi.h"
#include <ostream>
class Sashimi : public Sushi
{
std::string bed;
public:
Sashimi();
Sashimi(std::string bed);
~Sashimi();
std::string get_bed();
void set_bed(std::string b);
friend std::ostream &operator<<(std::ostream &os, const Sashimi &sh);
};
one of the derived classes operator overload function
std::ostream& operator<<(std::ostream& os, const Sashimi& sh)
{
os << "ID:" << sh.id << " Sashimi of " << sh.fish_type << " on a bed of: " << sh.bed << " cost: " << sh.cost << std::endl;
return os;
}

C++ Keep on getting an expression must have a class type?

I have a Person class which has a vector of Accounts. The account class is an abstract class and has a class type CurrentAccount. I have a method which will print out a Person account details called 'printAllAccounts'. But I see to be getting an error where it says 'accounts' and it says 'expression must have a class type'.
Here is the person header class:
Person.h
#include "pch.h"
#include "Account.h"
using namespace std;
class Person {
public:
Person(string);
void addAccount(Account &);
bool closeAccount(int *);
void printAllAccounts();
bool creditMoney(int *, double *);
bool debitMoney(int *, double *);
virtual ~Person();
private:
const string name;
vector<Account> accounts;
};
Here is the method for for Person.cpp:
void Person::printAllAccounts()
{
if (accounts.size() > 0) {
for (int i = 0; i < accounts.size(); i++)
{
//below line of accounts is where error is happening
cout << **accounts**.at(i).printDetails().c_str() << endl;
}
}
else {
cout << "Person : " << name << " has no accounts" << endl;
}
}
[Edit]
Here is print details in the Account Class:
Actually there is an error on return toRet;
Account.cpp file
void Account::printDetails() const
{
ostringstream conAcc, conBal;
conAcc << this->accountNo;
string toRet;
toRet += "Account No: ";
toRet += conAcc.str();
toRet += " Balance : ";
conBal << this->balance;
toRet += conBal.str();
return toRet;
}
Here is the Account.h header file(abstract class)
#include "pch.h"
using namespace std;
class Account {
public:
Account(int *, double *);
virtual ~Account();
bool debit(double *);
bool credit(double *);
int getAccNo();
//making it abstract
virtual double getBalance() const = 0;
virtual void printDetails() const;
private:
double balance;
int accountNo;
};
std::vector<Account> will internally create an array of Account and thus cannot store derived classes like CurrentAccount. Even if you add a CurrentAccount object, the vector will create a copy of type Account and store that. And if Account is abstract, you won't be able to store anything at all, since an abstract class cannot be instantiated. (You might want to look up object slicing to read more about what's going on.)
To fix this, you can use std::vector<std::unique_ptr<Account>>. That way your vector holds pointers of type Account*, which can point to derived classes like CurrentAccount.

Derived Members and Overloaded Ostream Operator

Working with a large number of derived classes whose members I would like to display with the << operator. As more classes are used it will likely become quite cumbersome to override the operator/other functions for the new members. I was curious if there was a way to accomplish something similar to the following? Which of course, will overflow.
// Base class
class Foo {
public:
friend ostream& operator <<(ostream& outputStream, const Foo& foo) {
outputStream << foo.fooName + ": " + foo.fooInfo + ", ";
return outputStream;
}
protected:
string fooName;
string fooInfo;
};
// Foo Derived class
class FooBar : public Foo {
public:
friend ostream& operator <<(ostream& outputStream, const FooBar& fooBar) {
outputStream << fooBar; // (fooBar.fooName + ": " + fooBar.fooInfo + ", ")
outputStream << fooBar.barName + ": " + fooBar.barInfo + ", ";
return outputStream;
/* The above as opposed to:
outputStream << fooBar.fooName + ": " + fooBar.fooInfo + ", " <<
fooBar.barName + ": " + fooBar.barInfo + ", "; */
}
protected:
string barName;
string barInfo;
};
If something similar (recursive) is not possible, what is an alternative solution? IE passing different argument(s) or calling an ostream/other function return within the operator body. Thanks.
This may help you out, however the Base class In this case is completely Abstract! Here are the Base & 2 Derived Classes
#include <conio.h>
#include <string>
#include <iostream>
class Base {
friend std::ostream& operator<<( std::ostream& out, const Base* const pObj );
private:
std::string m_strName;
public:
std::string getName() const { return m_strName; }
virtual ~Base(){} // Default Okay
protected:
explicit Base( std::string strName ) : m_strName( strName ) {}
virtual void printData( std::ostream& out ) const = 0;
};
std::ostream& operator<<( std::ostream& out, const Base* const pObj ) {
out << pObj->m_strName << std::endl;
pObj->printData( out );
return out;
}
class DerivedA : public Base {
private:
int m_value;
public:
explicit DerivedA( int& a ) : Base( std::string( "DerivedA" ) ), m_value( a ) {}
protected:
virtual void printData( std::ostream& out ) const override;
};
void DerivedA::printData( std::ostream& out ) const {
out << "Value: " << m_value;
}
class DerivedB : public Base {
private:
float m_value;
public:
explicit DerivedB( float& f ) : Base( std::string( "DerivedB" ) ), m_value( f ) {}
protected:
virtual void printData( std::ostream& out ) const override;
};
void DerivedB::printData( std::ostream& out ) const {
out << "Value: " << m_value;
}
int main () {
int a = 4;
float b = 3.2f;
DerivedA derivedA( a );
DerivedB derivedB( b );
// Notice I Used The Address Of Operator Here Due To How The << operator Is Defined
std::cout << &derivedA << std::endl << std::endl;
std::cout << &derivedB << std::endl << std::endl;
std::cout << "Press any key to quit" << std::endl;
_getch();
return 0;
}
Another way to use this instead of on the stack would be on the heap but make sure to clean up all memory.
int main () {
int a = 4;
float b = 3.2f;
DerivedA derivedA = new DerivedA( a );
DerivedB derivedB = new DerviedB( b );
// Since This Is On The Heap I Can Use The Class Directly
std::cout << derivedA << std::endl << std::endl;
std::cout << derivedB << std::endl << std::endl;
// Make Sure To Clean Up Memory
delete derivedA;
delete derivedB;
std::cout << "Press any key to quit" << std::endl;
_getch();
return 0;
}
What I ended up doing here is I created a friend << operator in the Base Class that will call a printData() function that is defined as being a purely virtual method. Remember that you can not construct a Base object directly since it is completely Abstract. Here each Derived type will have to implement its own printData() function! This way each class will know how to use the << operator since it is defined in the base class that it is inherited from. This is the power of Inheritance. So now I only have to defined the overloaded operator once and can use it for every derived type, but all derived types must specify a printData() function since each derived type may have different internal data that you would like to have printed.
If you do not want to use the pointer notation as I have defined within my Base Class << operator declaration & definition you can do it this way as well:
class Base {
friend std::ostream& operator<<( std::ostream& out, const Base& obj );
// Everything Else Is The Same As Before
};
std::ostream& operator<<( std::ostream& out, const Base& obj ) {
out << obj.m_strName << std::endl;
obj.printData( out );
}
int main() {
// Everything Is Same As Before As In The First main() example
// Except For The Two std::cout Statements Where As Here You
// Can Use The Objects Directly Instead Of Using The Address Of Operator
std::cout << derivedA << std::endl;
std::cout << derivedB << std::endl;
// Rest Is Same As Before.
}
If you want you can include both versions in your base class so that the stream operator << knows how to print your class either by object, reference or pointer!

Using Member Variables That Are Private c++

I added all my code.
The exact problem I am facing is when I make the member variables private in the game.h file I get an error in the game.cpp file that says n p h are all private members of game.h. in Xcode.
But when I compile the program from the command line it compiles fine with no errors.
I am trying to understand if I am doing something wrong or is this up to standards the way I am doing this?
This is main.cpp
#include "game.h"
int main() {
game g("Female", "Magic", true, 21, 5, 120);
std::cout << "These are the things every game needs to be a game" << '\n';
std::cout << g << '\n';
return 0;
}
game.cpp
#include <iostream>
#include "game.h"
std::ostream& operator<<(std::ostream& s, const game& g) {
return s << &g.n << ' ' << &g.p << ' ' << &g.h;
}
This is my composite class
#include <iostream>
#include "npc.h"
#include "pc.h"
#include "health.h"
class game {
private:
npc n;
pc p;
health h;
public:
game(const npc& init_n, const pc& init_p, const health& init_h):
n(init_n),
p(init_p),
h(init_h)
{}
game(std::string gen, std::string abil, bool use, int lvl, int h, int arm) :
n(gen, abil),
p(use, lvl),
h(h, arm)
{
}
friend std::ostream& operator<<(std::ostream& s, const game& g) {
g.n.output(s);
g.p.output(s);
g.h.output(s);
return s;
}
npc get_n() { return n; }
pc get_p() { return p; }
health get_h() { return h; }
void set_n(npc init_n) { n = init_n; }
void set_p(pc init_p) { p = init_p ; }
void set_h(health init_h) { h = init_h; }
};
Here is a class
#include <iostream>
class health {
private:
int hp;
int armor;
public:
health(int init_hp, int init_armor) :
hp(init_hp),
armor(init_armor)
{
}
public:
void output(std::ostream& s) const { s << "Characters have this amount of hit points "<< hp << " and an armor rating of " << armor << "\n"; }
};
Here is a class
class pc {
private:
bool user;
int level;
public:
pc(bool init_user, int init_level) :
user(init_user),
level(init_level)
{
}
public:
void output(std::ostream& s) const { s << "A player character has at least "<< user << " user and a level of " << level << '\n'; }
};
Here is a class
#include <iostream>
class npc {
private:
std::string gender;
std::string ability;
public:
npc(std::string init_gender, std::string init_ability) :
gender(init_gender),
ability(init_ability)
{
}
public:
void output(std::ostream& s) const { s << "A non player character has a gender of "<< gender << " and an ability of " << ability << '\n'; }
};
You made several errors - a typo is the reason for your problem.
The function is not allowed to access those members because it is not a friend of the class.
The friend is (correctly) std::ostream& operator<<(std::ostream& s, const game& g)
while you defined a function std::ostream& operator<<(std::ostream& s, const game g), note the missing ampersand.
Also, your accessors should be const, and return a const reference.
Ie,
npc const& get_n() const { return n; }
pc const& get_p() const { return p; }
health const& get_h() const { return h; }
Your manipulators change the wrong variables! You change the ones passed to the function instead of the members of that class.... However, it is highly questionable that you add direct manipulators for the three private members. You must view your class as some abstract object and define operators that work on that object. If you just give direct access to all it's members than there is little left of the object orientation idea behind using a class with private members (this would still be ten times better than making them public though!)
Finally, just a coding style hint. It is common practice to use CamelCase names for custom classes (ie, class Game), and you're better of adding a prefix to your private members to distinguish them from function parameters. Often people use the prefix m_. You really should use complete english words too (not abbreviations, let alone single characters).
This would turn your code into, say...
class Game {
private:
Npc m_npc;
Pc m_pc;
Health m_health;
public:
Game(Npc const& npc, Pc const& pc, Health const& health) :
m_npc(npc), m_pc(pc), m_health(health) { }
etc.

Reflect a class' inheritance tree in C++?

Say I have the following classes in C++, and I want to inspect their inheritance:
Vehicle
Motorcar is a Vehicle
Aircraft is a Vehicle
Biplane is an Aircraft is a Vehicle
Helicopter is an Aircraft is a Vehicle.
I want to write a method getClassLineage() to do the following:
Biplane b;
cout << b.getClassLineage() << endl; // prints "Vehicle--Aircraft--Biplane"
Helicopter h;
cout << h.getClassLineage() << endl; // prints "Vehicle--Aircraft--Helicopter"
Motorcar m;
cout << m.getClassLineage() << endl; // prints "Vehicle--Motorcar"
It seems like there should be a simple recursive way to do this by writing it once in the super-class, without duplicating an essentially identical method in every single one of the derived classes.
Assume we're willing to declare (pseudocode)Helicopter.className = "Helicopter" and
typedef Aircraft baseclass in each of the derived classes, but trying to avoid copying and pasting getClassLineage().
Is there an elegant way to write this?
(Thank you for your thoughts!)
Solution 1
IF you're okay with the decorated name, then you can write a free function template:
struct Vehicle {};
struct Aircraft : Vehicle { typedef Vehicle super; };
struct Helicopter : Aircraft { typedef Aircraft super; };
template<typename T>
string getClassLineage()
{
static string lineage = string(typeid(T).name()) +" - " + getClassLineage<typename T::super>();
return lineage;
}
template<>
string getClassLineage<Vehicle>()
{
static string lineage = string(typeid(Vehicle).name());
return lineage;
}
int main() {
cout << getClassLineage<Helicopter>() << endl;
return 0;
}
Output (decorated names):
10Helicopter - 8Aircraft - 7Vehicle
See at ideone: http://www.ideone.com/5PoJ0
You can strip off the decoration if you want. But it would be compiler specific! Here is a version that makes use of remove_decoration function to strip off the decoration, and then the output becomes :
Helicopter - Aircraft - Vehicle
By the way, as I said, the implementation of remove_decoration function is a compiler specific; also, this can be written in more correct way, as I don't know all cases which GCC considers, while mangling the class names. But I hope, you get the basic idea.
Solution 2
If you're okay with redefining the function in each derived class, then here is a simple solution:
struct Vehicle
{
string getClassLineage() const { return "Vehicle"; }
};
struct Aircraft : Vehicle
{
string getClassLineage() const { return Vehicle::getClassLineage()+" - Aircraft"; }
};
struct Helicopter : Aircraft
{
string getClassLineage() const { return Aircraft::getClassLineage()+" - Helicopter "; }
};
int main() {
Helicopter heli;
cout << heli.getClassLineage() << endl;
return 0;
}
Output:
Vehicle - Aircraft - Helicopter
See output at ideone: http://www.ideone.com/Z0Tws
If you want a recursive-like approach you can do it with virtual functions and explicit scoped function calls:
struct vehicle {
virtual std::string lineage() const { return "vehicle"; }
};
struct aircraft : vehicle {
typedef vehicle base;
virtual std::string lineage() const { return base::lineage() + "--aircraft"; }
};
struct biplane : aircraft {
typedef aircraft base;
virtual std::string lineage() const { return base::lineage() + "--biplane"; }
};
struct nieuport17 : biplane {
typedef biplane base;
virtual std::string lineage() const { return base::lineage() + "--nieuport17"; }
};
int main() {
biplane b;
aircraft const & a = b;
std::cout << a.lineage() << std::endl;
}
How does it work? When you call v.lineage() as it is a virtual function it the dynamic dispatch will make its way into biplane::lineage() as that is the actual type of the object. Inside that function there is a qualified call to its parent's lineage() function. Qualified calls do not use the dynamic dispatch mechanism, so the call will actually execute at the parents level. Basically this is what is going on:
a.lineage() -- dynamic dispatch -->
---> biplane::lineage()
\__ airplane::lineage()
\__ vehigcle::lineage()
<-- std::string("vehicle")
<-- std::string("vehicle") + "--airplane"
<-- std::string("vehicle--airplane") + "--biplane"
<--- std::string( "vehicle--airplane--biplane" )
[...]but trying to avoid copying and pasting getClassLineage().
As far as I know, that's not possible. C++ doesn't have reflection in and of itself, so the programmer has to do the work himself. The following C++0x version works under Visual Studio 2010, but I can't say for other compilers:
#include <string>
#include <typeinfo>
#include <iostream>
class Vehicle{
public:
virtual std::string GetLineage(){
return std::string(typeid(decltype(this)).name());
}
};
class Aircraft : public Vehicle{
public:
virtual std::string GetLineage(){
std::string lineage = std::string(typeid(decltype(this)).name());
lineage += " is derived from ";
lineage += Vehicle::GetLineage();
return lineage;
}
};
class Biplane : public Aircraft{
public:
virtual std::string GetLineage(){
std::string lineage = std::string(typeid(decltype(this)).name());
lineage += " is derived from ";
lineage += Aircraft::GetLineage();
return lineage;
}
};
class Helicopter : public Aircraft{
public:
virtual std::string GetLineage(){
std::string lineage = std::string(typeid(decltype(this)).name());
lineage += " is derived from ";
lineage += Aircraft::GetLineage();
return lineage;
}
};
int main(){
Vehicle v;
Aircraft a;
Biplane b;
Helicopter h;
std::cout << v.GetLineage() << std::endl;
std::cout << a.GetLineage() << std::endl;
std::cout << b.GetLineage() << std::endl;
std::cout << h.GetLineage() << std::endl;
std::cin.get();
return 0;
}
Output:
class Vehicle *
class Aircraft * is derived from class Vehicle *
class Biplane * is derived from class Aircraft *
class Helicopter * is derived from class Aircraft *
The output is slightly different at ideone, it drops the asterisk and decorates the name with a P at the beginning for pointer, but it works. Fun fact: trying to use typeid(decltype(*this)).name() crashed VS2010's compiler for me.
You need a static field to store the lineage, and each class will have its own lineage appended in its own static field.
If you are thinking about using typeid() or something like that, which is more complex but would avoid the repetition of the getClassLineage() method, remember that the name field attribute is annoyingly (the reason for this is beyond me) not the true name of the class, but a string that can be that name or any kind of mangled name (i.e., undefined representation).
You could easily apply a recursive aproach as the one you suggest if we were using Python or any other prototype-based programming language, in which inheritance is implemented by delegation, and thus the "inheritance path" can be followed.
#include <iostream>
#include <string>
class Vehicle {
public:
static const std::string Lineage;
Vehicle() {}
virtual ~Vehicle() {}
virtual const std::string &getClassLineage()
{ return Vehicle::Lineage; }
};
class Motorcar : public Vehicle {
public:
static const std::string Lineage;
Motorcar() {}
virtual ~Motorcar() {}
virtual const std::string &getClassLineage()
{ return Motorcar::Lineage; }
};
class Helicopter : public Vehicle {
public:
static const std::string Lineage;
Helicopter() {}
virtual ~Helicopter() {}
virtual const std::string &getClassLineage()
{ return Helicopter::Lineage; }
};
class Biplane : public Vehicle {
public:
static const std::string Lineage;
Biplane() {}
virtual ~Biplane() {}
virtual const std::string &getClassLineage()
{ return Biplane::Lineage; }
};
const std::string Vehicle::Lineage = "Vehicle";
const std::string Motorcar::Lineage = "Vehicle::Motorcar";
const std::string Helicopter::Lineage = "Vehicle::Helicopter";
const std::string Biplane::Lineage = "Vehicle::Biplane";
int main()
{
Biplane b;
std::cout << b.getClassLineage() << std::endl; // prints "Vehicle--Aircraft--Biplane"
Helicopter h;
std::cout << h.getClassLineage() << std::endl; // prints "Vehicle--Aircraft--Helicopter"
Motorcar m;
std::cout << m.getClassLineage() << std::endl; // prints "Vehicle--Motorcar"
return 0;
}
#include <iostream>
#include <ios>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <list>
#include <sstream>
using namespace std;
static const char *strVehicle = "Vehicle";
static const char *strMotorcar = "Motorcar";
static const char *strHelicopter = "Helicopter";
class Vehicle
{
private:
const char *ClassName;
protected:
int Lineage;
list<const char *> MasterList;
public:
Vehicle(const char *name = strVehicle)
{
MasterList.push_back(name);
}
virtual ~Vehicle() {}
virtual int getClassLineage() const
{
return Lineage;
}
string getName() const
{
list<const char *>::const_iterator it = MasterList.begin();
ostringstream ss( ios_base::in | ios_base::out );
while(it != MasterList.end())
{
ss << *(it++);
if(it != MasterList.end())
ss << " --> ";
}
ss << endl;
ss << ends;
return ss.str();
}
};
class Motorcar : public Vehicle
{
private:
const char *ClassName;
public:
Motorcar(const char *name = strMotorcar)
{
MasterList.push_back(name);
}
virtual ~Motorcar() {}
using Vehicle::getClassLineage;
using Vehicle::getName;
};
class Helicopter : public Vehicle
{
private:
const char *ClassName;
public:
Helicopter(const char *name = strHelicopter)
{
MasterList.push_back(name);
}
virtual ~Helicopter() {}
using Vehicle::getClassLineage;
using Vehicle::getName;
};
int _tmain(int argc, _TCHAR* argv[])
{
Helicopter h;
Motorcar m;
wcout << "Heli: " << h.getName().c_str() << endl;
wcout << "Motorcar: " << m.getName().c_str() << endl;
return 0;
}
If using typeid you don't need to hardcode strings (class' names). Solution for your problem could be:
#include <iostream>
#include <typeinfo>
using namespace std;
class Vehicle
{
public:
Vehicle();
string GetClassLineage(){return strName;}
protected:
string strName;
};
Vehicle::Vehicle() : strName(typeid(*this).name())
{
// trim "class "
strName = strName.substr(strName.find(" ") + 1);
}
class Motorcar : public Vehicle
{
public:
Motorcar();
};
Motorcar::Motorcar()
{
string strMyName(typeid(*this).name());
strMyName = strMyName.substr(strMyName.find(" ") + 1);
strName += " -- ";
strName += strMyName;
}
int main()
{
Motorcar motorcar;
cout << motorcar.GetClassLineage() << endl;
return 0;
}
Output:
Vehicle -- Motorcar