Cast to derived class without unique_ptr - c++

Background
I am creating a Cpp parser using Bison and Flex and I stumbled upon a problem: In my parser, I require a vector of base class objects, let's say shapes. Depending on which derived class an object has, I need to access different members. Thus, my intend was to store unique_ptr in the vector. Then upon access, I could dynamically cast them to their derived type.
The Problem
However, I can't get Bison to handle the unique_ptrs correctly. No matter how I specify the parser.yy file, upon compilation I run into errors like
usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
According to this post Bison does not handle unique_ptrs well (as far as I understand Bison does not use std::move() internally) and I assume that this is still the case.
My Question
As I would like to keep the class hierarchy as it is and don't want to fix bugs within Bison itself: Is there an alternative to using unique_ptrs when casting from Base class to Derived class?
Code Example
In particular, I want something like the following to work without using unique_ptrs.
enum Shape_type{
SHAPE_TYPE_CIRCLE,
SHAPE_TYPE_TRIANGLE,
};
class Shape{
public:
enum Shape_type type;
Shape(enum Shape_type type){ this->type=type; }
virtual ~Shape(){}
};
class Circle: public Shape{
int r;
public:
int get_r(){ return this->r; }
Circle(int r):Shape(SHAPE_TYPE_CIRCLE){ this->r=r; }
};
int main(void){
std::vector<std::unique_ptr<Shape>> shapes;
std::unique_ptr<Shape> circle_ptr = std::make_unique<Circle>(42);
shapes.push_back(std::move(circle_ptr));
for(auto& s_ptr: shapes){
switch(s_ptr->type){
case SHAPE_TYPE_CIRCLE:
{
auto c = dynamic_cast<Circle&>(*s_ptr);
std::cout << "circle with r=" << c.get_r() << std::endl;
break;
}
default: {
std::cout << "other shape" << std::endl;
break;
}
}
}
return 0;
}
Any help is greately appreciated. Thanks in advance.

The polymorphic way would be (replacing non-copiable std::unique_ptr by std::shared_ptr):
class Shape{
public:
virtual ~Shape() = default;
virtual void draw() const = 0;
};
class Circle: public Shape
{
int r;
public:
explicit Circle(int r): r(r) {}
int get_r() const { return r; }
void draw() const override { std::cout << "circle with r=" << r << std::endl; }
};
class Square: public Shape
{
int side;
public:
explicit Square(int side): side(side) {}
int get_side() const { return side; }
void draw() const override { std::cout << "square with side=" << side << std::endl; }
};
int main()
{
std::vector<std::shared_ptr<Shape>> shapes { std::make_shared<Circle>(42) };
for (const auto& shape_ptr: shapes)
{
shape_ptr->draw();
}
return 0;
}
With std::variant, you might do
class Circle
{
int r;
public:
explicit Circle(int r): r(r) {}
int get_r() const { return r; }
void draw() const { std::cout << "circle with r=" << r << std::endl; }
};
class Square
{
int side;
public:
explicit Square(int side): side(side) {}
int get_side() const { return side; }
void draw() const { std::cout << "square with side=" << side << std::endl; }
};
using Shape = std::variant<Circle, Square>;
int main()
{
std::vector<Shape> shapes { Circle(42) };
for (const auto& shape: shapes)
{
std::visit([](const auto& shape){ shape.draw(); }, shape);
}
return 0;
}

Related

How to get a subtype object saved in a supertype object to be recognized as a subtype

I have this problem which I really struggle to even explain(as you can guess by the title) so I'll make it clear by an example
#include <iostream>
using namespace std;
class shape
{
public:
shape()
{
}
};
class triangle : public shape
{
public:
triangle()
{
}
};
class square : public shape
{
public:
square()
{
}
};
class shapeTeller
{
public:
shapeTeller() {}
void tellMeWhatShape(square s)
{
cout << "Hello, I'm a square\n";
}
void tellMeWhatShape(triangle t)
{
cout << "Hello, I'm a triangle\n";
}
void tellMeWhatShape(shape s)
{
cout << "Hello, I'm a generic shape\n";
}
};
int main()
{
shape sh;
triangle tr;
square sq;
shape shapeArray[3] = {sh, tr, sq};
shapeTeller tell;
for (auto &element : shapeArray)
{
tell.tellMeWhatShape(element);
}
}
this snippet of code prints three times "Hello, I'm a generic shape", while my desired output would be
"Hello, I'm a generic shape"
"Hello, I'm a triangle"
"Hello, I'm a square"
How can i achieve something like that, considering that I want the array to be of the superclass, and I want it to contains various subclasses?
I also want to make it clear that this is a simplified exhample but in the real implementation I can't use parametric polymorphism cause i want the shapeTeller class' methods to do completely different things.
Thanks a lot
Note: An array can only store a single type of object. A subtype of the object could be an entirely different size which is not something compatible with the way C++ stores arrays.
You could be using std::variant here to allow every array element to store one of several element types here:
class shapeTeller
{
public:
shapeTeller() {}
void tellMeWhatShape(square s)
{
std::cout << "Hello, I'm a square\n";
}
void tellMeWhatShape(triangle t)
{
std::cout << "Hello, I'm a triangle\n";
}
void tellMeWhatShape(shape s)
{
std::cout << "Hello, I'm a generic shape\n";
}
void tellMeWhatShape(std::variant<square, triangle, shape> const& s)
{
std::visit([this](auto const& shape)
{
tellMeWhatShape(shape);
},
s);
}
};
int main()
{
shape sh;
triangle tr;
square sq;
std::variant<square, triangle, shape> shapeArray[3] = { sh, tr, sq };
shapeTeller tell;
for (auto& element : shapeArray)
{
tell.tellMeWhatShape(element);
}
}
Alternatively dynamically allocate the shapes and implement the visitor pattern:
class shape;
class triangle;
class square;
struct Visitor
{
virtual void operator()(shape const&) = 0;
virtual void operator()(triangle const&) = 0;
virtual void operator()(square const&) = 0;
};
class shape
{
public:
virtual ~shape() = default;
shape()
{
}
virtual void Accept(Visitor& v) const
{
v(*this);
}
};
class triangle : public shape
{
public:
triangle()
{
}
void Accept(Visitor& v) const override
{
v(*this);
}
};
class square : public shape
{
public:
square()
{
}
void Accept(Visitor& v) const override
{
v(*this);
}
};
class shapeTeller
{
public:
shapeTeller() {}
void tellMeWhatShape(square s)
{
std::cout << "Hello, I'm a square\n";
}
void tellMeWhatShape(triangle t)
{
std::cout << "Hello, I'm a triangle\n";
}
void tellMeWhatShape(shape s)
{
std::cout << "Hello, I'm a generic shape\n";
}
};
int main()
{
auto sh = std::make_unique<shape>();
auto tr = std::make_unique<triangle>();
auto sq = std::make_unique<square>();
std::unique_ptr<shape> shapeArray[3] = { std::move(sh), std::move(tr), std::move(sq) };
shapeTeller tell;
struct ShapeTellerVisitor : Visitor
{
ShapeTellerVisitor(shapeTeller& teller)
: m_teller(teller)
{}
shapeTeller& m_teller;
virtual void operator()(shape const& s) override
{
m_teller.tellMeWhatShape(s);
}
virtual void operator()(triangle const& s) override
{
m_teller.tellMeWhatShape(s);
}
virtual void operator()(square const& s) override
{
m_teller.tellMeWhatShape(s);
}
};
ShapeTellerVisitor visitor{ tell };
for (auto& element : shapeArray)
{
element->Accept(visitor);
}
}
Note: You could implement Visitor with shapeTeller directly.

How to manage different types of data in the base class?

My goal is to separate data from various implementations. I don't want my things to know what actual subclass it is they are working with, either way around. To make things perform only a single task with minimal information.
I'll throw some code in your eyes first.
// Example program
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <functional>
class Model
{
public:
virtual bool set(int p_attrId, int p_value) {return false;};
virtual bool get(int p_attrId, int & p_value) const {return false;};
};
class Derived: public Model
{
static constexpr int c_classId = 1;
int value = 1;
public:
enum EAttrs
{
eAttr1 = c_classId * 1000
};
virtual bool set(int p_attrId, int p_value) override
{
switch(p_attrId)
{
case eAttr1:
value = p_value;
return true;
default:
return Model::set(p_attrId, p_value);
}
}
virtual bool get(int p_attrId, int & p_value) const override
{
switch(p_attrId)
{
case eAttr1:
p_value = value;
return true;
default:
return Model::get(p_attrId, p_value);
}
}
};
// GuiTextBoxComponent.h
// no includes to any class derived from model
class GuiTextBoxComponent
{
std::weak_ptr<Model> m_model;
int m_attrId;
public:
void draw()
{
auto locked = m_model.lock();
if(locked)
{
int value;
bool result = locked->get(m_attrId, value);
if(!result)
{
std::cout << "Failed to get attribute " << m_attrId << "\n";
return;
}
std::cout << "AttrID: " << m_attrId << " Value: " << value << "\n";
}
else
{
std::cout << "Model is dead\n";
}
}
void setSource(std::weak_ptr<Model> p_model, int p_attrId)
{
m_model = p_model;
m_attrId = p_attrId;
}
};
int main()
{
std::shared_ptr<Model> model (new Derived);
GuiTextBoxComponent textbox;
textbox.setSource(model, Derived::eAttr1);
textbox.draw();
}
The motivation behind this is acquisition of all data from a single interface.
I need to be able to add functionality like the GuiTextBoxComponent, without #include "Derived1.h" in its header.
The challenge with this design is that the Model interface needs to implement all types required from anywhere in the program.
How would you extend the types provided?
Is there some other design that could be used to achieve similar results?
Generally, I think this is an XY problem but here is how you can beautify your code a bit. First, I implemented two interfaces: Getter and Setter like:
enum class EAttrs {
eAttr1
};
template <typename GetterImpl>
struct Getter {
bool get(EAttrs const attrId, int& value) {
switch (attrId) {
case EAttrs::eAttr1:
return static_cast<GetterImpl*>(this)->get(value);
default:
return false;
}
}
};
template <typename SetterImpl>
struct Setter {
bool set(EAttrs const attrId, int value) {
switch (attrId) {
case EAttrs::eAttr1:
return static_cast<SetterImpl*>(this)->set(value);
default:
return false;
}
}
};
Here I used CRTP, i.e. static polymorphism. Then implementation of your derived classes is a bit simpler:
class Derived1 : public Getter<Derived1>, Setter<Derived1> {
int value = 1;
public:
bool set(int p_value) {
value = p_value;
return true;
}
bool get(int & p_value) {
p_value = value;
return true;
}
};
class Derived2 : public Getter<Derived1>, Setter<Derived1> {
int value = 2;
public:
bool set(int p_value) {
value = p_value;
return true;
}
bool get(int & p_value) {
p_value = value;
return true;
}
};
Finally, since we were using CRTP, there is no need for creating std::unique_ptr. Code that's using above classes could look like:
template <typename T>
void printInt(Getter<T>& model, EAttrs p_attrId) {
int value;
bool result = model.get(p_attrId, value);
if (!result)
{
std::cout << "Failed to get attribute " << static_cast<int>(p_attrId) << "\n";
return;
}
std::cout << "AttrID: " << static_cast<int>(p_attrId) << " Value: " << value << "\n";
}
int main()
{
Derived1 derived1;
Derived2 derived2;
printInt(derived1, EAttrs::eAttr1);
printInt(derived2, EAttrs::eAttr1);
}
Check out the DEMO.
P.S. Note the usage of enum class instead of plain enum.
Take a look at this CppCon's talk about Solid principles. Your code might be a good example to apply those principles to.

boost::variant and polymorphism in c++11

I am experimenting with polymorphism and boost::variant in c++11
Here is the code
#include <iostream>
#include <boost/variant.hpp>
using namespace std;
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{
width=a;
height=b;
}
};
class Rectangle: public Polygon {
public:
Rectangle() {
std::cout << "ctor rectangle" << std::endl;
}
int area()
{
return width*height;
}
};
class Triangle: public Polygon {
public:
Triangle() {
std::cout << "ctor triangle" << std::endl;
}
int area()
{
return width*height/2;
}
};
int main () {
Triangle r;
boost::variant<Rectangle, Triangle> container = r;
int x = 4;
int y = 5;
if (container.type() == typeid(Rectangle)) {
r.set_values(x,y);
std::cout << r.area() << std::endl;
} else if ( container.type() == typeid(Triangle)){
r.set_values(x,y);
std::cout << r.area() << std::endl;
}
return 0;
}
I am wondering if this is the best way to proceed. There is a repetition in the code (in main() function) where for every type (we get the type at runtime) we execute the same thing, ie set value and print the area.
Is there any better way to do this?
This is a helper class for when you want value-type variant based polymorphism.
template<class Base>
struct poly_ptr_t : boost::static_visitor<Base*> {
template<class T>
Base* operator()(T& t)const { return std::addressof(t); }
template<class...Ts>
Base* operator[](boost::variant<Ts...>& v) const {
return boost::apply_visitor( *this, v );
}
template<class...Ts>
Base const* operator[](boost::variant<Ts...> const& v) const {
return boost::apply_visitor( *this, v );
}
};
Use:
poly_ptr_t<Polygon> as_polygon;
int main() {
boost::variant<Triangle, Rectangle> u(Triangle{});
as_polygon[u]->set_values(x,y);
}
Now, area is a bit of a pain. Getting the parent Polygon won't help, because it doesn't have an area.
If we added
virtual int area() = 0;
to Polygon then
std::cout << as_polygon[v]->area();
suddenly works.
The alternative is a bit of a mess in C++11. In C++14 with appropriate boost support, we get:
std::cout << boost::apply_visitor( [](auto& e){return e.area();}, v );
or
boost::apply_visitor( [](auto& e){std::cout << e.area();}, v );
where we use a generic lambda to call area.
Or we can write an area visitor:
struct get_area : boost::static_visitor<int> {
template<class T>
int operator()(T& t)const{ return t.area(); }
};
now we can do this:
std::cout << boost::apply_visitor( get_area, v );
In none of these cases do we have the code repetition within main.
Don't use if-else constructs.
Take a look at boost. I typed a small and untested example below.
#include "boost/variant.hpp"
#include <iostream>
class my_visitor : public boost::static_visitor<void>
{
public:
void operator()(Rectangle const & i) const
{
// do something here
}
void operator()(Triangle const & i) const
{
// do something here
}
};
int main()
{
boost::variant< Triangle, Rectangle > u(Triangle());
boost::apply_visitor( my_visitor(), u );
}

Can I implement Factory-pattern construction without using new()?

At the moment I'm dealing with a delightful legacy code class implementing polymorphism by switch-case:
class LegacyClass {
public:
enum InitType {TYPE_A, TYPE_B};
void init(InitType type) {m_type=type;}
int foo() {
if (m_type==TYPE_A)
{
/* ...A-specific work... */
return 1;
}
// else, TYPE_B:
/* ...B-specific work... */
return 2;
}
/** Lots more functions like this **/
private:
InitType m_type;
};
I'd like to refactor this to proper polymorphism, e.g.:
class RefactoredClass {
public:
virtual ~RefactoredClass(){}
virtual int foo()=0;
};
class Class_ImplA : public RefactoredClass {
public:
virtual ~Class_ImplA(){}
int foo() {
/* ...A-specific work... */
return 1;
}
};
class Class_ImplB : public RefactoredClass {
public:
virtual ~Class_ImplB(){}
int foo() {
/* ...B-specific work... */
return 2;
}
};
Unfortunately, I have one crucial problem: due to optimization and architectural considerations, within a primary use of LegacyClass, I cannot use dynamic allocation; the instance is a member of a different class by composition:
class BigImportantClass{
/* ... */
private:
LegacyClass m_legacy;
}
(In this example, BigImportantClass may be dynamically allocated, but the allocation needs to be in one continuous virtual segment, and a single new() call; I can't make further calls to new() in the BigImportantClass ctor or in subsequent initialization methods.)
Is there a good way to initialize a concrete implementation, polymorphically, without using new()?
My own progress so far: What I can do is provide a char[] buffer as a member of BigImportantClass, and somehow initialize a concrete member of RefactoredClass in that memory. The buffer would be large enough to accommodate all implementations of RefactoredClass. However, I do not know how to do this safely. I know the placement-new syntax, but I'm new to dealing with alignment (hence, warned off by the C++-FAQ...), and aligning generically for all concrete implementations of the RefactoredClass interface sounds daunting. Is this the way to go? Or do I have any other options?
Here's some code... just doing the obvious things. I don't use C++11's new union features, which might actually be a more structured way to ensure appropriate alignment and size and clean up the code.
#include <iostream>
template <size_t A, size_t B>
struct max
{
static const size_t value = A > B ? A : B;
};
class X
{
public:
X(char x) { construct(x); }
X(const X& rhs)
{ rhs.interface().copy_construct_at_address(this); }
~X() { interface().~Interface(); }
X& operator=(const X& rhs)
{
// warning - not exception safe
interface().~Interface();
rhs.interface().copy_construct_at_address(this);
return *this;
}
struct Interface
{
virtual ~Interface() { }
virtual void f(int) = 0;
virtual void copy_construct_at_address(void*) const = 0;
};
Interface& interface()
{ return reinterpret_cast<Interface&>(data_); }
const Interface& interface() const
{ return reinterpret_cast<const Interface&>(data_); }
// for convenience use of virtual members...
void f(int x) { interface().f(x); }
private:
void construct(char x)
{
if (x == 'A') new (data_) Impl_A();
else if (x == 'B') new (data_) Impl_B();
}
struct Impl_A : Interface
{
Impl_A() : n_(10) { std::cout << "Impl_A(this " << this << ")\n"; }
~Impl_A() { std::cout << "~Impl_A(this " << this << ")\n"; }
void f(int x)
{ std::cout << "Impl_A::f(x " << x << ") n_ " << n_;
n_ += x / 3;
std::cout << " -> " << n_ << '\n'; }
void copy_construct_at_address(void* p) const { new (p) Impl_A(*this); }
int n_;
};
struct Impl_B : Interface
{
Impl_B() : n_(20) { std::cout << "Impl_B(this " << this << ")\n"; }
~Impl_B() { std::cout << "~Impl_B(this " << this << ")\n"; }
void f(int x)
{ std::cout << "Impl_B::f(x " << x << ") n_ " << n_;
n_ += x / 3.0;
std::cout << " -> " << n_ << '\n'; }
void copy_construct_at_address(void* p) const { new (p) Impl_B(*this); }
double n_;
};
union
{
double align_;
char data_[max<sizeof Impl_A, sizeof Impl_B>::value];
};
};
int main()
{
{
X a('A');
a.f(5);
X b('B');
b.f(5);
X x2(b);
x2.f(6);
x2 = a;
x2.f(7);
}
}
Output (with my comments):
Impl_A(this 0018FF24)
Impl_A::f(x 5) n_ 10 -> 11
Impl_B(this 0018FF04)
Impl_B::f(x 5) n_ 20 -> 21.6667
Impl_B::f(x 6) n_ 21.6667 -> 23.6667
~Impl_B(this 0018FF14) // x2 = a morphs type
Impl_A::f(x 7) n_ 11 -> 13 // x2 value 11 copied per a's above
~Impl_A(this 0018FF14)
~Impl_B(this 0018FF04)
~Impl_A(this 0018FF24)
I implemented this using C++11 unions. This code seems to work under g++ 4.8.2, but it requires the -std=gnu++11 or -std=c++11 flags.
#include <iostream>
class RefactoredClass {
public:
virtual ~RefactoredClass() { }; // Linking error if this is pure. Why?
virtual int foo() = 0;
};
class RefactorA : RefactoredClass {
double data1, data2, data3, data4;
public:
int foo() { return 1; }
~RefactorA() { std::cout << "Destroying RefactorA" << std::endl; }
};
class RefactorB : RefactoredClass {
int data;
public:
int foo () { return 2; }
~RefactorB() { std::cout << "Destroying RefactorB" << std::endl; }
};
// You may need to manually create copy, move, &ct operators for this.
// Requires C++11
union LegacyClass {
RefactorA refA;
RefactorB refB;
LegacyClass(char type) {
switch (type) {
case 'A':
new(this) RefactorA;
break;
case 'B':
new(this) RefactorB;
break;
default:
// Rut-row
break;
}
}
RefactoredClass * AsRefactoredClass() { return (RefactoredClass *)this; }
int foo() { return AsRefactoredClass()->foo(); }
~LegacyClass() { AsRefactoredClass()->~RefactoredClass(); }
};
int main (void) {
LegacyClass A('A');
LegacyClass B('B');
std::cout << A.foo() << std::endl;
std::cout << B.foo() << std::endl;
return 0;
}
Somebody should have made an answer by now...so here's mine.
I'd recommend using a union of char array and one of the biggest integer types:
union {
char refactored_class_buffer[ sizeof RefactoredClass ];
long long refactored_class_buffer_aligner;
};
I also strongly recommend putting an assert or even an if(check) throw; into your factory so that you never, ever, exceed the size of your buffer.
If the data is the same for each case, and you're only changing behaviuor, you don't need to allocate in your core - this is basically a strategy pattern using singleton strategies. You end up using polymorphism in your logic, but not in your data.
class FooStrategy() {
virtual int foo(RefactoredClass& v)=0;
}
class RefactoredClass {
int foo() {
return this.fooStrategy(*this);
}
FooStrategy * fooStrategy;
};
class FooStrategyA : public FooStrategy {
//Use whichever singleton pattern you're happy with.
static FooStrategyA* instance() {
static FooStrategyA fooStrategy;
return &fooStrategy;
}
int foo(RefactoredClass& v) {
//Do something with v's data
}
}
//Same for FooStrategyB
Then when you create a RefactoredClass you set its fooStrategy to FooStrategyA::instance().

how to pass class to method, and from base class detect inheritor?

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);
}