here is my problem:
code:
file1.hpp:
namespace Output {
class Stringify{ // base class.....
protected:
size_t prec;
public:
std::stringstream out;
public:
Stringify(const size_t& _p = 5): prec(_p) {out.precision(prec);}
virtual ~Stringify(void){}
public:
std::string operator()(const XYZ& _v){
out.str("");
out << "{ " << _v.x() << ", " << _v.y() << ", " << _v.z() << " }";
return out.str();
}
std::string operator()(const XYZ& _v, const bool& _status){
out << "{ " << _v.x() << ", " << _v.y() << ", " << _v.z() << " }";
return out.str();
}
};
}
where XYZ is a vector object.
file2.hpp:
namespace NODE {
class Stringify: public Output::Stringify {
public:
Stringify2(const size_t& _p = 5): Output::Stringify(_p) {}
virtual ~Stringify2(void){}
public:
std::string operator()(const VERTEX& _obj){ return "What?";}
};
}
where VERTEX is another object with members values of type XYZ
main.cpp:
int main(int argc,char * argv[]){
XYZ v(1,2,3);
NODE::Stringify printer;
cout << printer(v) << endl;
return 0;
}
output is:
What?
when it should:
be {1,2,3}
Compilation is ok but,
As far as I know, NODE::Stringify is able to print {1,2,3}, because of, his base object
has inherit the method for XYZ argument, but it prints the Method with the arguments
of VERTEX (What?). virtual word is not neccesary, because I do not overwrite a method in
the base class.
As a information: I am compiling in MAC OS 10.8 with llvm-gcc-4.2
using Eigen 3.0 libs (typedef Eigen::vector3d XYZ)
Any idea?
Thanks in advance.
Your operator () in the derived class hides the operator () overloads from the base class (which you name Stringify in your example, but that's probably a typo, since the constructor and destructor are named (~)Stringify2).
You can fix this through a using declaration inside the derived class:
namespace NODE {
class Stringify2 : public Output::Stringify {
// ^
public:
using Output::Stringify::operator ();
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// This should fix the problem
Stringify2(const size_t& _p = 5): Output::Stringify(_p) {}
virtual ~Stringify2(void){}
public:
std::string operator()(const VERTEX& _obj){ return "What?";}
};
}
Related
I'm implementing the Visitor pattern, and I have an accept() function that is only defined in the base visitable class. This system works just fine, but Alexandresku states in his book that the this pointer has static typing.
Is this code flawed and/or has a bug, but my output is not catching it?
I have tried to change references to pointers, but the output does not change.
.h file
class WidgetVisitor
{
public:
virtual void visit(ConcreteWidget1& w1);
virtual void visit(ConcreteWidget2& w2);
virtual void visit(Widget& w);
virtual ~WidgetVisitor() { }
};
class Widget
{
public:
Widget(const std::string& text);
virtual std::string text() const;
virtual void accept(WidgetVisitor* v);
protected:
std::string text_;
};
class ConcreteWidget1: public Widget
{
public:
ConcreteWidget1(const std::string& text);
virtual std::string text() const override;
};
class ConcreteWidget2: public Widget
{
public:
ConcreteWidget2(const std::string& text);
virtual std::string text() const override;
};
.cpp file
void WidgetVisitor::visit(ConcreteWidget1& w1) {
cout << w1.text() << '\n';
}
void WidgetVisitor::visit(ConcreteWidget2& w2) {
cout << w2.text() << '\n';
}
void WidgetVisitor::visit(Widget& w) {
cout << w.text() << '\n';
}
Widget::Widget(const std::string& text): text_(text) { }
string Widget::text() const {
return "Widget" + text_;
}
void Widget::accept(WidgetVisitor* v) {
v->visit(*this);
cout << "in the class " << text_ << '\n';
}
ConcreteWidget1::ConcreteWidget1(const string& text): Widget(text) { }
string ConcreteWidget1::text() const {
return "ConcreteWidget1" + text_;
}
ConcreteWidget2::ConcreteWidget2(const string& text): Widget(text) { }
string ConcreteWidget2::text() const {
return "ConcreteWidget2" + text_;
}
main.cpp
int main() {
WidgetVisitor* visitor = new WidgetVisitor();
std::vector<Widget*> v;
v.push_back(new Widget(" 1"));
v.push_back(new ConcreteWidget1(" 2"));
v.push_back(new ConcreteWidget2(" 3"));
v.push_back(new ConcreteWidget1(" 4"));
for (auto & w: v)
w->accept(visitor);
return 0;
}
Output is:
Widget 1
in the class 1
ConcreteWidget1 2
in the class 2
ConcreteWidget2 3
in the class 3
ConcreteWidget1 4
in the class 4
This isn't actually working like you think it's working. The only visitor being called is void WidgetVisitor::visit(Widget& w) but since the Widget::text() method is virtual, all of the visitor methods effectively have the same behavior.
Change the implementations to output the name of the reference argument's type and you'll see:
void WidgetVisitor::visit(ConcreteWidget1& w1) {
cout << "[cw1] " << w1.text() << '\n';
}
void WidgetVisitor::visit(ConcreteWidget2& w2) {
cout << "[cw2] " << w2.text() << '\n';
}
void WidgetVisitor::visit(Widget& w) {
cout << "[w] " << w.text() << '\n';
}
You get this output:
[w] Widget 1
in the class 1
[w] ConcreteWidget1 2
in the class 2
[w] ConcreteWidget2 3
in the class 3
[w] ConcreteWidget1 4
in the class 4
So as you can see, the other two visitor overloads are simply not being used.
this is indeed statically typed; if it points to a polymorphic type then virtual methods called on it are still dispatched using dynamic dispatch, but Widget::accept() isn't actually invoking anything on this, it's just taking a reference to it. When you pass this reference somewhere else it will still be treated as its static type, meaning that overload resolution is still going to pick the Widget& overload here, because this is always Widget*:
v->visit(*this);
This can work but you have to override Widget::accept() in derived classes. For example:
class ConcreteWidget1: public Widget
{
public:
ConcreteWidget1(const std::string& text);
virtual std::string text() const override;
virtual void accept(WidgetVisitor* v) override;
};
void ConcreteWidget1::accept(WidgetVisitor* v) {
v->visit(*this);
cout << "in the class " << text_ << '\n';
}
Do the same for ConcreteWidget2 and now you'll notice that the right visitor overload is called:
[w] Widget 1
in the class 1
[cw1] ConcreteWidget1 2
in the class 2
[cw2] ConcreteWidget2 3
in the class 3
[cw1] ConcreteWidget1 4
in the class 4
Now you'd be able to make Widget::text() non-virtual and see exactly the same output.
I have a problem with my code. I have two classes, A and B, and B inherits A. I also have operators << overloaded in both classes.
Everything works, I have no compiler errors, but it seems something is wrong. As far as I understand polymorphism, when I use pointers to base class while creating child class with new, calling a method should match the child class, not the base class.
For the code below,
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
A(int aa) : a(aa) {};
virtual void show(ostream& o) const
{
o << "a = " << a << "\n";
}
};
ostream& operator << (ostream& os, const A &o)
{
o.show(os);
return os;
}
class B : public A
{
private:
int b;
public:
B(int bb, int aa) : A(aa), b(bb){}
int getb() const {return b;}
};
ostream & operator << ( ostream & os, const B & o)
{
os << static_cast <const A &>(o);
os << "\n";
os << "b = " << o.getb() << "\n";
return os;
}
int main()
{
A *o1 = new B(2,3);
cout << *o1;
cout << "---------------------\n";
B *o2 = new B(2,3);
cout << *o2;
return 0;
}
In main:
A *o1 = new B(2,3);
cout << *o1;
Shows a = 3, instead of showing a = 3 b = 2 (the call should match the child class, not the base class). The thing is, I need to implement the << and >> operators in every child class, but I think they do not behave as they should.
The output of the program:
Even the modified code with re-implmented show method shows wrong results, it does not show a at all this time:
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
A(int aa) : a(aa) {};
virtual void show(ostream& o) const
{
o << "a = " << a << "\n";
}
};
ostream& operator << (ostream& os, const A &o)
{
o.show(os);
return os;
}
class B : public A
{
private:
int b;
public:
B(int bb, int aa) : A(aa), b(bb) {}
int getb() const
{
return b;
}
void show(ostream& o) const
{
o << "b = " << b << "\n";
}
};
ostream & operator << ( ostream & os, const B & o)
{
os << static_cast <const A &>(o);
o.show(os);
return os;
}
int main()
{
A *o1 = new B(2,3);
cout << *o1;
cout << "---------------------\n";
B *o2 = new B(2,3);
cout << *o2;
return 0;
}
enter image description here
you have to implement the virtual function show in derived class B:
class B: public A
{
public:
// some code here
virtual void show(ostream& o) const
{
o << "b = " << b << "\n";
}
};
when I use pointers to base class while creating child class with new,
calling a method should match the child class, not the base class
It does when you call a member function ("method" in some other languages), but operator<< is not a member function – it's an overloaded free function.
When choosing an overload, only the types known at compile-time are used.
Since o1 is an A*, *o1 is an A&, and the overload for A& is chosen.
You're doing this a bit "backwards"; you only need one operator<<, for the base class, which calls the virtual show, and then you override show in the derived classes.
Like this:
class A
{
// ...
virtual void show(ostream& o) const
{
o << "a = " << a << "\n";
}
};
ostream& operator << (ostream& os, const A &o)
{
o.show(os);
return os;
}
class B : public A
{
// ...
void show(ostream& o) const override
{
A::show(o); // Do the "A part".
o << "b = " << b << "\n";
}
};
Follow the same pattern for 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!
It's hard to explain exactly what I want to do here, but I have a base class and two classes which inherit this base class. Both classes which inherit it have their own unique members. I want to be able to pass both to a method, and have that method detect which it is, then access their unique members. I can't assume there will only be two classes which inherit it, so i'm looking for something of a more general solution.
Here is an example of what I'd like to do:
#include <iostream>
class Base {
public:
int _type;
Base() { }
};
class First : public Base {
public:
int _first_only;
First() { }
};
class Second : public Base {
public:
int _second_only;
Second() { }
};
void test (Base b) {
std::cout << "Type: " << b._type << std::endl;
if(b._type==1) {
std::cout << "First\n";
// Want to be able to do this
std::cout << "Val: " << (First)b._first_only << std::endl;
} else if(b._type==2) {
std::cout << "Second\n";
// And this
std::cout << "Val: " << (Second)b._second_only << std::endl;
}
}
int main() {
First f;
f._first_only=1;
f._type=1;
Second s;
s._type=2;
s._second_only=2;
test(f);
test(s);
}
This is similar to others answers:
You can write polymorphic classes to get this behavior using virtual functions.
Pass the Dervied class objects either by pointer or by reference to get polymorphic behaviour. Otherwise it will lead to object slicing. Your test() function leads to object slicing.
This code may also help you. You can see that there are different ways to print the type. I used GetBaseType(), GetDerivedType() and GetType(). Among these GetType() method is convenient for you case. There are two constructors for convenience. Constructors allow to initialize data members.
class Base {
private:
int _type;
public:
Base(int type) : _type(type) { }
int GetBaseType() { return _type; }
virtual int GetDerivedType() = 0;
virtual int GetType() { return _type; }
};
class First : public Base {
private:
int _first_only;
public:
First() : Base(1), _first_only(1) { }
First(int first_only) : Base(first_only), _first_only(first_only) { }
int GetDerivedType() { return _first_only; }
virtual int GetType() { return _first_only; }
};
class Second : public Base {
private:
int _second_only;
public:
Second() : Base(2), _second_only(2) { }
Second(int second_only) : Base(second_only), _second_only(second_only) { }
int GetDerivedType() { return _second_only; }
virtual int GetType() { return _second_only; }
};
void test (Base &b) {
std::cout << "Type: " << b.GetBaseType() << std::endl;
std::cout << "Type: " << b.Base::GetType() << std::endl;
std::cout << "Dervied type: \n";
std::cout << "Val: " << b.GetDerivedType() << std::endl;
std::cout << "Val: " << b.GetType() << std::endl;
}
int main() {
First f(1);
Second s(2);
test(f);
test(s);
First f1;
Second s1;
test(f1);
test(s1);
}
Either declare a virtual function in Base
Move the common members types from First and Second into Base.
For your specific problem, 2nd option is better:
class Base {
public:
int _member; // have getter() method, if '_member' is private
Base() { }
};
Inside, test():
void test (Base &b) { // <--- practice to pass by reference if copy is not needed
// use b._member;
};
Your code does not work polymorphically, because you are passing the function-parameter by value, which results in slicing.
If you have a method that does different things for different types, consider overloading it for each of these types.
Three things I'd do:
In general switching on type codes is not considered good object oriented design: Instead pull the switched code into the classes.
I'd also set up the type tags in the constructor of the specific classes.
And as others have mentioned you need to pass the argument by reference to avoid slicing.
Here's what the code would look like:
#include <iostream>
class Base {
public:
int _type;
Base() { }
virtual void print_to_stream( std::ostream & os ) const =0;
};
class First : public Base {
public:
int _first_only;
First() { _type =1; }
void print_to_stream( std::ostream & os ) const
{
os<<"First\n";
os<<"Val: " << _first_only << std::endl;
}
};
class Second : public Base {
public:
int _second_only;
Second() { _type=2; }
void print_to_stream( std::ostream & os ) const
{
os << "Second\n";
os << "Val: " << _second_only << std::endl;
}
};
void test (Base & b)
{
std::cout << "Type: " << b._type << std::endl;
b.print_to_stream( std::cout );
}
int main() {
First f;
f._first_only=1;
Second s;
s._second_only=2;
test(f);
test(s);
}
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