One pointer, two different classes in c++ - c++

Suppose I have two structures a and b, each hold several variable in them (most of the variable are c++ core types but not all).
Is there a way to create a a pointer named c that can point to either one of them? Alternatively, is there a way to create a set that can hold either one of them?
Thanks

The usual way to create a pointer that can point to either of the two is to make them inherit from a common base-class. Any pointer of the base-class can point to any sub-class. Note that this way you can only access elements that are part of the base-class through that pointer:
class Base {
public:
int a;
};
class Sub1 : public Base {
public:
int b;
};
class Sub2 : public Base {
public:
int c;
};
int main() {
Base* p = new Sub1;
p.a = 1; // legal
p.b = 1; // illegal, cannot access members of sub-class
p = new Sub2; // can point to any subclass
}
What you are trying to achieve is called polymorphism, and it is one of the fundamental concepts of object oriented programming. One way to access member of the subclass is to downcast the pointer. When you do this, you have to make sure that you cast it to the correct type:
static_cast<Sub1*>(p).b = 1; // legal, p actually points to a Sub1
static_cast<Sub2*>(p).c = 1; // illegal, p actually points to a Sub1
As for your second question, using the technique described above, you can create a set of pointers to a base-class which can then hold instance of any of the subclasses (these can also be mixed):
std::set<Base*> base_set;
base_set.insert(new Sub1);
base_set.insert(new Sub2);

Alternatively, is there a way to create a set that can hold either one
of them?
Take a look at Boost.Any and Boost.Variant. If you have just 2 classes, then variant should suffice. If you plan other types, and don't want to recompile this 'set', then use any.
Then use any container of either any or variant.
#include <boost/any.hpp>
#include <boost/variant.hpp>
#include <vector>
class A { };
class B { };
class C { };
int main()
{
// any
std::vector<boost::any> anies;
anies.push_back(A());
anies.push_back(B());
A a0 = boost::any_cast<A>(anies[0]);
A b0 = boost::any_cast<A>(anies[1]); // throws boost::bad_any_cast
// variant
std::vector<boost::variant<A,B> > vars;
vars.push_back(A());
vars.push_back(B());
A a1 = boost::get<A>(vars[0]);
A b1 = boost::get<A>(vars[1]); // throws boost::bad_get
// and here is the main difference:
anies.push_back(C()); // OK
vars.push_back(C()); // compile error
}
Edit: having more than 2 classes is of course possible for variant, too. But extending variant so it is able to hold a new unanticipated type without recompilation is not.

If a and b are unrelated, then you can use a void* or, better, a boost any type.
If a is superclass of b, you can use an a* instead.

If they both inherit from the same type you can do it. Thats how OOP frameworks work, having all classes inherit from Object.

Although you can do that, what would that pointer mean? If any portion of your application gets hold on the pointer to 'either a or b', it cannot do a lot with it, unless you provide extra type information.
Providing extra type information will result in client code like
if( p->type == 'a' ) {
... a-specific stuff
} else if( p->type == 'b' ) {
... b-specific stuff
} ...
Which isn't very useful.
It would be better to delegate 'type-specificness' to the object itself, which is the nature of object-oriented design, and C++ has a very good type-system for that.
class Interface {
public:
virtual void doClientStuff() = 0; //
virtual ~theInterface(){};
};
class A : public Interface {
virtual void doClientStuff(){ ... a-specific stuff }
};
class B : public Interface {
virtual void doClientStuff(){ ... b-specific stuff }
};
And then your client code will become more type-unaware, since the type-switching is done by C++ for you.
void clientCode( Interface* anObject ) {
anObject->doClientStuff();
}
Interface* i = new A();
Interface* j = new B();
clientCode( i );
clientCOde( j );

There are several ways to do this:
Using the more generic base type, if there is an inheritance relationship.
Using void* and explicitly casting where appropriate.
Creating a wrapper class with the inheritance relationship needed for #1.
Using a discriminating container via union.
Since others have already described the first three options, I will describe the fourth. Basically, a discriminated container uses a union type to use the storage of a single object for storing one of multiple different values. Typically such a union is stored in a struct along with an enum or integral type for distinguishing which value is currently held in the union type. As an example:
// Declarations ...
class FirstType;
class SecondType;
union PointerToFirstOrSecond {
FirstType* firstptr;
SecondType* secondptr;
};
enum FIRST_OR_SECOND_TYPE {
FIRST_TYPE,
SECOND_TYPE
};
struct PointerToFirstOrSecondContainer {
PointerToFirstOrSecond pointer;
FIRST_OR_SECOND_TYPE which;
};
// Example usage...
void OperateOnPointer(PointerToFirstOrSecondContainer container) {
if (container.which == FIRST_TYPE) {
DoSomethingWith(container.pointer.firstptr);
} else {
DoSomethingElseWith(container.pointer.secondptr);
}
}
Note that in the code below, "firstptr" and "secondptr" are actually two different views of the same variable (i.e. the same memory location), because unions share space for their content.
Note that even though this is a possible solution, I seriously wouldn't recommend it. This kind of thing isn't very maintainable. I strongly recommend using inheritance for this if at all possible.

Just define a common superclass C and two subclasses A, B of C. If A and B have no common structure (no common attributes), you can leave C empty.
The define:
A *a = new A();
B *b = new B();
C *c;
Then you can do both
c = a;
or
c = b;

Abstract Class !!!! -- simple solutions
To have a base class that can be used as a pointer to several derived sub classes. (no casting needed)
Abstract class is define when you utilize a virtual method in it. Then you implement this method in the sub-class... simple:
// abstract base class
#include <iostream>
using namespace std;
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area (void) =0;
};
class Rectangle: public Polygon {
public:
int area (void)
{ return (width * height); }
};
class Triangle: public Polygon {
public:
int area (void)
{ return (width * height / 2); }
};
int main () {
Polygon * ppoly1 = new Rectangle (4,5);
Polygon * ppoly2 = new Triangle (4,5);
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
cout << ppoly1->area() << '\n';
cout << ppoly2->area() << '\n';
return 0;
}

Related

using smart pointers in a derived class constructor

The question, at the outset: (preface: new to c++ oop programming)
How do I construct a derived class, Widget, such that I have a vector of (shared?) pointers in terms the base class, where the original objects (such that they are still of the derived class) can be accessed upon casting and dereferencing the pointers?
Say I have a base class:
class Component {
public:
int a;
int b;
virtual void rtti(){}; // for run time type information.
explicit Component(int a, int b) { this->a = a; this->b = b;}
}
And two derived classes,
class AComponent:public Component{
public:
using Component::Component;
AComponent(int a, int b) : Component(int a, int b){}
}
class BComponent:public Component{
public:
using Component::Component;
BComponent(int a, int b) : Component(int a, int b){}
}
Further, I have a Multi-Component (still generic here):
typedef shared_ptr<AComponent> AComponentPtr;
typedef shared_ptr<BComponent> BComponentPtr;
class MultiComponent{
public:
vector<AComponentPtr> A_components;
vector<BComponentPtr> B_components;
explicit MultiComponent(vector<AComponentPtr> As, vector<BComponentPtr> Bs){
this->A_components = As;
this->B_components = Bs;
}
}
Finally, I have a specific use case of this component hierarchy:
class WidgetComponentA:public AComponent{...}
class WidgetComponentB:public BComponent{...}
class Widget:public MultiComponent{
public:
using MultiComponent::MultiComponent;
Widget(WidgetComponentA a, WidgetComponentB b, WidgetComponentB c)
: MultiComponent(???){
}
}
Currently, I have the MultiComponent class constructor within Widget set up as follows:
class Widget:public MultiComponent{
public:
using MultiComponent::MultiComponent;
Widget(WidgetComponentA a, WidgetComponentB b, WidgetComponentB c)
: MultiComponent({(AComponentPtr)&a},{(BComponentPtr)&b, (BComponentPtr)&c}){}
}
Because this yields no errors on compilation.
Then, I construct the widget in my main method like so:
main(){
WidgetComponentA a = WidgetComponentA(1,2);
WidgetComponentB b = WidgetComponentB(3,4);
WidgetComponentB c = WidgetComponentB(5,6);
// now, the widget:
Widget widget = Widget(a,b,c);
// however, the pointers within the widget
// do not access valid addresses in memory.
return 0;}
The shared pointers within the Widget widget object do not reference any valid locations in memory, and fail with,
Attempt to take address of value not located in memory.
Ultimately, what I am trying to do is have Widget just hold on to the list of components of various derived types in the form of the base class shared pointers.
Then, I run generic, template functions on the class, and only cast the pointers to the widget-specific derived class pointers in functions specific to widgets.
I am using shared pointers to be safe, because I ran into the memory leak warnings...but if there is a simpler solution...
As I suggested in the comments, perhaps a polymorphic approach would be easier...
class MultiComponent{
public:
typedef std::vector<std::shared_ptr<Component>> components_vec;
components_vec components;
MultiComponent(components_vec& cv){
components = cv;
}
}
class Widget: public MultiComponent {
public:
Widget(MultiComponent::components_vec& cv)
: MultiComponent(cv){}
}
You can cast pointers to descendants of Component to Component*'s and then store them together.
Then, perhaps define a virtual void Component::display() = 0 to force the inheritors to define some sort of behaviour to your needs.
Perhaps I misunderstand what you ask but if you want to deal with objects of shared ownership then you have to make them such:
main()
{
auto a = std::make_shared<WidgetComponentA>(1,2);
auto b = std::make_shared<WidgetComponentB>(3,4);
auto c = std::make_shared<WidgetComponentB>(5,6);
// now, pass the shared stuff to widget:
Widget widget = Widget(a,b,c); // make sure that Widget has
// such constructor that accepts
// the shared pointers
return 0;
}

Pointer to a Class Type

Essentially I'm trying to work around the problem of not being able to store derived types as a derived type in a (value) array of a base type. I have multiple classes that store one to three ints but have to have very different sets of functions. I'd use an array of pointers but the entire array is traversed forwards, then backwards constantly, mostly linearly, so keeping it all together in memory is preferable. I could create multiple arrays, one for each type and then an array of pointers to each of those, but that would get pretty clumsy fast and really wouldn't be the same as each element packed neatly between the one preceding it and the one proceeding it in order of access at runtime.
So what I'm thinking is that I make a POD struct with three ints and a pointer and fill an array with those, then use that pointer to access polymorphic functions. It would end up something along these lines: (forgive the poor coding here, I'm just trying to convey the concept)
class A {
int aa( &foo f ) { return 1; }
int dd() { return 9; }
};
class B : A {
int aa( &foo f ) { return f.b; }
};
class C : A {
int aa( &foo f ) { return cc() + f.c - f.a; }
int cc() { return 4; }
};
class D : B {
int dd() { return 7; }
};
struct foo{ int a, b, c; A* ptr; };
const A AA = A(); const B BB = B(); const C CC = C(); const D DD = D();
foo[100] foos;
init() {
foo[0] = foo{ 1, 2, 3, &BB };
// etc fill foos with various foo elements
}
bar(){
for ( int i = 0; i < 100; ++i ){
print foos[i].ptr.aa( &foos[i] );
print foos[i].ptr.dd();
}
}
main(){
init();
while(true)
bar();
}
I'm just wondering if this is the best way to go about what I want to achieve or if there's a better solution? Ideally I'd just point to a class rather than an instance of a class but I don't think I can really do that... ideally I'd store them in an array as multiple derived types but for obvious reasons that's not going to fly.
What you are looking for are virtual functions.
In the bellow example :
class A
{
virtual void foo(){printf("A is called");};
}
class B : public A
{
void foo(){printf("B is called");};
}
...
A* ptr = new B();
ptr->foo();
Will produce "B is called" .
If you don't want to use virtual functions (to save memory for example), you can use dynamic cast , but this will lead to significant performance loss.
Please not that you need to have at least 1 virtual function to perform dynamic cast.
In the example bellow :
class A {...}
class B : public A {...}
class C : public A {...}
A* ptr1 = new C();
B* ptr2 = dynamic_cast<B*>(ptr1);
C* ptr3 = dynamic_cast<C*>(ptr1);
ptr2 will be null, and ptr3 will have a value.
So you can make the following (very wrong) construct :
if (ptr2)
{
ptr2->bb();
} else if (ptr3)
{
ptr3->cc();
}
Finally, you can get rid of dynamic casting by having your own typing mechanism and then just C cast to the correct class.
You need polymorphism. In your example all the classes have standard methods. You need to make them virtual, so the polymorphism can be applied.
class A {
virtual int aa( foo& f )const { return 1; }
virtual int dd()const { return 9; }
};
class B : A {
virtual int aa( foo& f )const { return f.b; }
};
class C : A {
virtual int aa( foo& f )const { return cc() + f.c - f.a; }
int cc()const { return 4; }// this doesn't need to be virtual because is not in the base class A
};
class D : B {
virtual int dd()const { return 7; }
};
Here is some information on this topic: http://www.cplusplus.com/doc/tutorial/polymorphism/. There is some information on how to use pointers as well.
I would suggest to look at smart pointers: http://www.cplusplus.com/reference/memory/shared_ptr/?kw=shared_ptr
Another topic you should look at is constness: search for "constness c++" (cannot post more then 2 links)
struct foo{ int a, b, c;const A* ptr; }; // const A* instead of A*
... I'm trying to work around the problem of not being able to store derived types as a derived type in a (value) array of a base type.
You can store derived types, as values, in an array - you just can't store them as instances of the base type.
A union of your concrete leaf types is almost what you want, but there's no way to figure out which member of the union is live, or to use polymorphic dispatch.
A discriminated union is one which tells you which member is live, but doesn't directly help with the dispatch.
Boost.Variant is a specific discriminated union which provides a clean mechanism for polymorphic dispatch - not using virtual, but using a visitor with overloads for each concrete stored type. In this case, you don't even need the stored types to be related to a common abstract base - they can be entirely unrelated. Look for apply_visitor in the tutorial for details.

c++: Construct derived object via base class interface

I have a template class which is constructed by taking two arguments, an integer and a previous instance of that class. I want to be able to store instances of those classes in containers, which is why I have it inheriting from a base class (please ignore the non-smart pointers):
class base {
virtual base* getNext(unsigned x) = 0;
};
template <class D>
class derived :
public base {
/* no memory allocation here, simply changes the data in next */
void construct_impl(unsigned x, const derived<D>& previous, derived<D>& next);
derived(); /* default constructor */
derived(unsigned x, const derived<D>& previous) { /* construct from previous object */
allocate_memory_for_this();
construct_impl(x, previous, *this);
}
base* getNext(unsigned x) {
return new derived(x, *this);
}
};
Now I would like to create a function in the base class which will construct an object of derived<D> in the same way as construct_impl does, ie without allocating memory anew.
I was thinking something like this
class base {
virtual base* getNext(unsigned x) = 0;
virtual void getNext_noalloc(unsigned x, base* already_allocated_derived_object) = 0;
}
which will be overriden in the derived class like this
void getNext_noalloc(unsigned x, base* already_allocated_derived_object) {
construct_impl(x, *this, *already_allocated_derived_object);
}
which unfortunately does not compile since there is no conversion from base* to derived<D>* (unless I use a static_cast). Is there any way to achieve what I need? Thanks in advance!
The curiously recurring template pattern that David Nehme linked to in the comments might do what you're looking for. It shouldn't keep you from storing objects of the derived class together in the same container. It does look like you're implementing a doubly-linked list with automatic creation of the next item from a given one. (This would invalidate the list from that element to the end unless it is the tail.)
I believe (I haven't tried it yet) you should test a dynamic_cast<> in the overrides for getNext_noalloc() to test the next pointer and call the matching class's construct_impl().
// override in derived class
void getNext_noalloc(unsigned x, base* already_allocated_derived_object) {
derived<D1>* p1 = dynamic_cast< derived<D1> >(already_allocated_derived_object);
derived<D2>* p2 = dynamic_cast< derived<D2> >(already_allocated_derived_object);
if(p1 != NULL) {
p1->construct_impl(x, *this, *p1); // 2nd parameter should take base type
} else if(p2 != NULL) {
p2->construct_impl(x, *this, *p2); // 2nd parameter should take base type
}
}
This does assume that the two classes know about each other, so you have to have the function definitions after the classes have been declared, and if construct_impl() is private or protected, the classes will have to be friends.
Using dynamic_cast<>() should mean you don't need the CRTP after all, but you will have to check each cast to ensure it converts to the correct type.
Casting pointers from base type to child type
You may be laboring under the misapprehension that it's possible in C++ to write
class ClownCar {
unsigned int x;
ClownCar inner_car;
};
But this is impossible! What would sizeof(ClownCar) be? It would have to be at least sizeof x + sizeof inner_car; i.e., sizeof(unsigned int) + sizeof(ClownCar); i.e., at least four bytes bigger than itself.
So, a class can't contain an instance of its own class. Inheritance, virtual or otherwise, is irrelevant here. So what do we do? We use pointers!
class ClownCar {
unsigned int x;
ClownCar *inner_car;
public:
ClownCar() : x(0), inner_car(nullptr) {}
ClownCar(unsigned int x, ClownCar *previous) : x(x), inner_car(previous) {}
ClownCar *getNext(unsigned int x) {
return new ClownCar(x, this);
}
};
int main() {
ClownCar inmost_car;
ClownCar *car1 = inmost_car.getNext(42);
ClownCar *car2 = car1.getNext(43);
// ...
delete car2;
delete car1;
// of course we don't delete inmost_car, since it lives on the stack
}
Of course this isn't very C++ish. We probably want to get rid of all these *s, and also make it so that each car "takes ownership" of its inner car (and takes responsibility for deleting it, too). We can do this using the Standard Library's std::unique_ptr to represent this concept of "ownership" (see also How do I pass a unique_ptr argument to a constructor or a function?)... but really, all we've got here is a singly-linked list of ClownCars, and that's something that the STL gives us for free:
struct ClownCar { unsigned int x; };
typedef std::list<ClownCar> ClownCarList; // ta-da!
So I think the real question is, what are you trying to accomplish?

How to search through and assign from a collection of c++ derived objects?

I got a good answer to the technical part of my question as to why my current approach to this is not working (assigning derived** to base** is type-unsafe, see also Converting Derived** to Base** and Derived* to Base*). However, I still don't have a good idea of how to implement what I'm thinking of in a C++ manner. I'm starting a new question, since the last title was too specific.
Here's perhaps a clearer explanation of what I am trying to do:
Create a number of objects which are all instances of classes derived from one single class.
Store these objects in some type of master container along with a compile-time human-readable identifier (probably a string?).
Get a list of identifiers from other components, search through the master container, and pass them back (pointers/references to) the corresponding objects so they can read/modify them. I think I need to break type-safety at this point and assume that the components know the derived type that they are asking for by identifier.
I thought this would be relatively simple and elegant to do with maps, vectors, and pointers to objects (I give a simplified example in my my previous question), but it seems I'm going to have to be doing a lot of C-style type casting to allow the components to pass pointers to the locations to store the value from the master container. This indicates to me that I'm not following a C++ paradigm, but what "should" I do?
[Edit] Here's some hypothetical sample code for how I envisioned this, hope this clarifies my thinking:
#include <map>
#include <vector>
#include <string>
using namespace std;
class BaseObj {};
class Der1Obj: public BaseObj {};
class Der2Obj: public BaseObj {};
typedef map<string, BaseObj**> ObjPtrDict;
typedef map<string, BaseObj*> ObjDict;
class BaseComp
{
public:
ObjPtrDict objs;
};
class DervComp
{
DervComp(){objs["d1"] = &d1; objs["d2"] = &d2; } // This wouldn't compile
Der1Obj* d1;
Der2Obj* d2;
}
typedef vector<BaseComp*> CompList;
void assign_objs(CompList comps, ObjDict objs)
{
for (auto c = comps.begin(); c != comps.end(); c++)
for (auto o = c.objs.begin(); o != c.objs.end(); o++)
*(o->second) = objs[o->first];
}
int main(int argc, char* argv[])
{
Der1Obj d, d1;
Der2Obj d2;
ObjDict objs;
objs["d"] = &d;
objs["d1"] = &d1;
objs["d2"] = &d2;
DervComp c;
vector<DervComp*> comps;
comps.push_back(&c);
assign_objs(comps, objs);
return 0;
}
If I got what you want right, you can do it like this:
#include <vector>
class Base
{
public:
enum eDerived
{
//name these whatever you like
DER1,//for first derived class
DER2,//for second derived class
DER3//for third derived class
};
virtual eDerived type() = 0;//this will return the class type.
};
class Derived1: public Base
{
public:
virtual eDerived type() { return DER1; }
};
class Derived2: public Base
{
public:
virtual eDerived type() { return DER2; }
};
class Derived3: public Base
{
public:
virtual eDerived type() { return DER3; }
};
int main()
{
std::vector<Base*> myList;//container for all elements
//You can store a pointer to any of the derived classes here like this:
Base * a = new Derived1();
Base * b = new Derived2();
Base * c = new Derived3();
myList.push_back(a);
myList.push_back(b);
myList.push_back(c);
//Iterating through the container
for( Base * tmp: myList)
{
//You can check the type of the item like this:
if( tmp->type() == Base::DER1 )
{
//and cast to a corresponding type.
//In this case you are sure that you are casting to the right type, since
//you've already checked it.
Derived1 * pointerToDerived1 = static_cast<Derived1 *>(tmp);
}
}
}
Ofc you can choose any type of container. If you want to give them an ID, you could either use map, or add it into the class itself.
I read your other post, but I think I donĀ“t understand why you would use double pointers. In my understanding you would just use a normal pointer.
E.g.
class Base
{
};
class Deriv : public Base
{
};
std::map< std::string, Base* > ObjectStore;
function Component1( ... )
{
Base* b = ObjectStore[ "MyObject" ];
b->DoSomeFancyStuff();
}
function ModifyObjectStore( )
{
delete ObjectStore[ "MyObject" ];
ObjectStore[ "MyObject" ] = new Derived();
}
I hope this helps.
You says, "pass them back the corresponding object". For this why do you want to pass back the base**? You can simply give back the a map from string to pointer back. Please see the code below for explanation.
class Container
{
void add(const string& aKey_in, Base* b)
{
myObjects[aKey_in] = b;
}
void getObjs(list<string> aKeys_in, map<string,Base*>& anObjMap_out)
{
for(all string s in the aKeys_in)
anObjMap_out[s] = myObjects[s];
}
private:
map<string, base*> myObjects;
};
You conditions meet here:
Create a number of objects which are all instances of classes derived from one single class.
You could extend the class to have creation logic, factory logic etc.
Store these objects in some type of master container along with a compile-time human-readable identifier (probably a string?).
Achieved with the map
Get a list of identifiers from other components, search through the master container, and pass them back (pointers/references to) the corresponding objects so they can read/modify them. I think I need to break type-safety at this point and assume that the components know the derived type that they are asking for by identifier.
You don't need to pass back the pointer to pointer to the client. Just pass back the object pointers.
Additional note:
You could implement the pointers with shared_ptr instead of raw pointers.
If your client code (whoever is using the getObjs() method) is written properly then you won't need a dynamic cast from base pointer to derived pointer. They should be able to work with the base pointer.
Anyway, that is a different question which you haven't asked yet.

Conditional variable declaration

I'm coming from Python and I have some problem with managing types in c++. In Python I can do something like this:
if condition_is_true:
x=A()
else:
x=B()
and in the rest of the program I can use x without caring about the type of x, given that I use methods and member variables with the same name and arguments (not necessary that A and B have the same base classes).
Now in my C++ code type A corresponds to
typedef map<long, C1> TP1;
and B to:
typedef map<long, C2> TP2;
where:
typedef struct C1
{
char* code;
char* descr;
int x;
...
}
and
typedef struct C2
{
char* code;
char* other;
int x;
...
}
C1 and C2 have similar members and in the part of code I'm talkin of I only have to use the ones with the same name/type
I would like to do something like:
if (condition==true)
{
TP1 x;
}
else
{
TP2 x;
}
what is the correct approach in c++?
thanks in advance
If the condition is known at compile-time, you can use std::conditional. This is useful in generic code.
typedef std::conditional<
std::is_pointer<T>::value
, TP1
, TP2
>::type map_type;
map_type x;
(where the test is made-up; here we're testing whether T is a pointer type or not)
If the condition cannot be known until runtime, then some form of dynamic polymorphism is needed. Typical instances of such polymorphism in C++ are subtyping, boost::variant or when push comes to shove, boost::any. Which one you should pick* and how you should apply it depends on your general design; we don't know enough.
*: very likely not to be boost::any.
You have a couple of choices. If C1 and C2 are both POD types, you could use a union, which allows access to the common initial sequence:
struct C1 {
// ....
};
struct C2 {
// ...
};
union TP {
C1 c1;
C2 c2;
};
union TP x;
std::cout << x.c1.code; // doesn't matter if `code` was written via c1 or c2.
Note that to keep the initial sequence "common", you really want to change the names so the second member (descr/other) has the same name in both versions of the struct.
If they're not PODs, you can use inheritance to give you a common type.
C++, however, doesn't have a direct counterpart to Python's famous "duck typing". While templates provide type erasure (to at least some degree), you'd end up with kind of the reverse of what you're doing in Python. Instead of the variation between the two types happening where you deal with the variable, you'd allow code to deal with two different types that had common syntax. This is different, however, in that it requires that the compiler be able to resolve the actual type being used with any particular template at compile time, not just run time.
If you really need to resolve the type at run time, then templates probably won't work -- you'll probably need to use a union or base class.
If you really need two different types, the best thing to do would be (assuming the classes are similar and has some similar member functions) to have an abstract class, say, CBase (see http://www.cplusplus.com/doc/tutorial/polymorphism/) and then define two subclasses C1 and C2 of this abstract class.
Now your code can be written as follows:
CBase *x;
if (condition) {
x = new C1();
} else {
x = new C2();
}
In case you can not abstract C1 and C2 into a common abstract class, well, then you'll need two different variables and condition acts like your flag using which you can know later which variable has been populated and which structure to work with.
Although there may be some ways to do it, they're mostly tricky and not maintainable, just as Damon mentioned.
I recommend you to use template function. What you really want is to access the same member/functions for different class. In template function, you can access the object of a "general type" as long as the type provides the operation you use in the template.
For example, in your case you can simply extract the common parts into a template function like this.
struct TP1
{
// common part
int i;
int j;
// different part
float f;
};
struct TP2
{
// common part
int i;
int j;
// different part
double d;
};
template<typename CType>
void f(CType a)
{
// as long as CType has variable i, j
cout << a.i << endl;
cout << a.j << endl;
}
int main(int argc, char* argv[])
{
bool choice;
// get a choice from console during runtime
cin >> choice;
if (choice)
{
TP1 x = {0, 0};
f(x);
}
else
{
TP2 x = {1, 1};
f(x);
}
return 0;
}
i think you can do it by runtime polymorphism.
class C_Base { /*all common variables*/ } ;
class C1 : public C_Base { ... };
class C2 : public C_Base { ... };
typedef map<long, C_Base *> TP;
{
...
TP x;
if (condition)
/*use x as if values are C1 * */
else
/*other way round*/
}
In order to use two different types through a common variable, the types
must have a common base class. Since what you have is two different
types which you can't change, and which don't have a common base class,
you need some sort of duck typing. In C++, only templates use duck
typing: one solution would be to move all of the code after the
condition into a separate function template, to which you pass the
results, and then write something like:
if ( condition_is_true )
wrapped_code( A() );
else
wrapped_code( B() );
Depending on the code that actually follows the condition, this may be
more or less convenient.
A more general alternative is to create your class hierarchy to wrap the
maps. This solution is a bit verbose, but very easy: just define a base
class with the interface you want, say:
class Map
{
public:
virtual ~Map() {}
virtual std::string getCode( long index ) const = 0;
virtual std::string getDescr( long index ) const = 0;
virtual int getX( long index ) const = 0;
};
, and then a template which derives from it:
template <typename T> // Constraint: T must have accessible members code, other and x
class ConcreteMap : public Map
{
std::map <long, T> myData;
public:
virtual std::string getCode( long index ) const
{
return myData[index].code;
}
virtual std::string getDescr( long index ) const
{
return myData[index].descr;
}
virtual int getX( long index ) const
{
return myData[index].x;
}
};
Your if then becomes:
std::unique_ptr<Map> x = (condition_is_true
? std::unique_ptr<Map>( new ConcreteMap<C1> )
: std::unique_ptr<Map>( new ConcreteMap<C2> ));
What you're trying to do is not possible in C++. Variables in C++ have a fixed type which is defined at compile time and they can't change type at run time. But C++ does provide polymorphism (which looks like dynamic types) which allows derived types to implement base class functionality, but the only way to access type specific methods is to have a type bound to the base class, if you have a type bound to the derived type then you can only call that type's implementation*:
class Base
{
public: virtual void Func () = 0;
};
class C1 : public Base
{
public: virtual void Func () {}
};
class C2 : public Base
{
public: virtual void Func () {}
};
void SomeFunc ()
{
C1 *c1 = new C1;
C2 *c2 = new C2;
Base *b;
b = c1;
b->Func (); // calls C1::Func
b = c2;
b->Func (); // calls C2::Func
}
It looks like b has changed type, but it's actual type has remained the same, it is always a Base * and it can only be assigned the value c1 and c2 because they share a common base class Base. It is possible to go the other way:
Base *b = new C1;
C1 *c1 = dynamic_cast <C1 *> (b);
but it requires the dynamic_cast and that requires something called RTTI (Run-Time Type Information) which provides the compiled code a way to check that b is actually pointing to a C1 type. If you were to do the following:
Base *b = new C2;
C1 *c1 = dynamic_cast <C1 *> (b);
c1 would be the null pointer, not b. But C1 and C2 must still have a common base class for this to work. This is not legal:
class Base {....}
class C1 : public Base {....}
class C2 {....} // not derived from Base!
Base *b = new C2; // no way to convert C2 to Base!
C2 *c2 = new C2;
b = dynamic_cast <Base *> (c2); // still won't work, C2 not a Base
b = new C1; // fine, C1 is a Base
C1 *c1 = new C1;
b = c1; // again, fine
c1 = dynamic_cast <C1 *> (b); // fine, C1 is a derived type of Base, this will work
c2 = dynamic_cast <C2 *> (b); // won't work, C2 is not a derived type of Base
If C1 and C2 are related (say, CSquare and CCircle) then a common base class makes sense. If they are not related (say, CRoad and CFood) then a common base class won't help (it can be done, but it's not very logical). Doing the former (common base class) has been well described in the other answers. If you need to do the latter, then you may need to re-think how the code is structured to allow you to do the former.
It would help if you could expand on what you want to do with x. Since x is a container, do you just want to do container related operations?
Of course, things are never that easy in C++ and there are many things that can confuse the issue. For example, a derived type may implement a public base class virtual method privately:
Example:
class B
{
public:
virtual void F () = 0;
};
class C : public B
{
private:
virtual void F () { .... }
};
C *c = new C;
B *b = c;
b->F (); // OK
c->F (); // error