As I am still somewhat new to programming in C++ I was just curious if it were possible to pass objects pointers to an array in order for code consolidation.
Header file like such;
class.h
class parent
{
some information.....
};
class child1 : public parent
{
some information.....
};
class child2 : public parent
{
some information.....
};
Main file like such;
main.cpp
#include "class.h"
int main()
{
child1 instanceChild1;
child2 instanceChild2;
child1* pointer1 = &instanceChild1;
child2* pointer2 = &instanceChild2;
parent array[2] = {pointer1 , pointer2};
}
I am trying to achieve such so that I may create a function that uses a dynamic array in order to hold object pointers so that I may dereference them in the function and manipulate them accordingly. Though I am having issues getting the different pointers to work together when going into an array. I need such functionality since there will be many different objects(all under the same parent) going in and out of this function.
Yes it is possible.
But you need to declare the array like this
parent * arr[] = { ... }
or it would be better if you use a vector
vector<parent *> arr;
arr.push_back(childPointer);//For inserting elements
as #pstrjds and #basile has written
and if you want to use child specific member functions, you can use dynamic cast
ChildType1* ptr = dynamic_cast<ChildType1*>(arr.pop());
if(ptr != 0) {
// Casting was succesfull !!! now you can use child specific methods
ptr->doSomething();
}
else //try casting to another child class
** your compiler should support RTTI in order for this to work correctly
you can see this answer for details
I prefer to use pure Virtual functions like this
class A {
public :
enum TYPES{ one , two ,three };
virtual int getType() = 0;
};
class B : public A{
public:
int getType()
{
return two;
}
};
class C : public A
{
public:
int getType()
{
return three;
}
};
Related
Hello everyone and thanks for reading,
I'm new to working with classes and I've ran into an issues with making array's of objects,
I have a base class, and an array of the same type, I'd like to know if it's a possibility to
make subclasses of the base class type and put them into an array and call methods that're not
in the base class, sorry if this is a bad question and my apologies if my wording is off,
#include <iostream>
int main()
{
BaseClass* ObjectList[10];
ObjectList[0] = new SubClass;
ObjectList[0]->Load(10);
ObjectList[0]->OtherFunction(); // How Can I Do This?
return 0;
}
class BaseClass
{
public:
virtual void Load(int Num) = 0;
};
class SubClass : public BaseClass
{
void Load(int Num) override
{
std::cout << Num << std::flush;
}
void OtherFunction()
{
// Do Something
}
};
Thanks
Edit -
My intent is to have a simple base class with dozens and dozens of subclasses with different methods, and have an array of the base class,
You can always have more than one pointer (or reference) to the same object.
int main()
{
BaseClass* ObjectList[10];
SubClass TheSubclass;
ObjectList[0] = &TheSubclass;
ObjectList[0]->Load(10); // presumably in a loop
TheSubclass.OtherFunction();
return 0;
}
You will have to downcast your pointer to the real class (or at least a class having the method). You can use either a static_cast if you do not need any control, or a dynamic_cast if you want a run-time validation of the cast:
...
SubClass *psc = dynamic_cast<SubClass *>(ObjectList[0]);
if (psc != nullptr) { // an invalid cast would set it to NULL
psc->OtherFunction();
}
else {
// process the error
}
I have somes difficults with inheritance in C++. Suppose I have a class base Parent:
class Parent{
public:
...
virtual Parent Intersection(Parent anotherParent);
}
and 2 classes children Numeric and Symbolic with implement of method Intersection:
class Numeric : public Parent{
public:
...
Numeric Intersection(Numeric anotherNumeric)
{
...
}; // do intersection with another object numeric
}
// class Symbolic
class Symbolic : public Parent{
public:
...
symbolic Intersection(Symbolic anotherSymbolic)
{
...
}; // do intersection with another object symbolic
}
and a last class ParentVector:
class ParentVector : public Parent{
public:
...
ParentVector Intersection(ParentVector anotherParentVector);
private:
std::vector<Parent> vtParent; // vector stock object Parent (Numeric or Symbolic)
}
I want vector vtParent stock 2 types of object: Numeric or Symbolic. So I created a vector of Parent objects.
The problem is: I want get Intersection of 2 vectors ParentVector.
I can add an object Numeric or Symbolic in vector vtParent but I can not call the method Intersection correspond each type of object. It always call method Intersection of class Parent.
Anyone have some ideas or suggestions ? Many thanks.
//edit : I forgot that the class ParentVector is a child of Parent class, too.
// UPDATE: thanks for all your useful helps. Now, I want to execute the code below to calculate the Intersection of 2 vectors Parent :
ParentVector* Intersection(ParentVector anotherParentVector){
ParentVector* result;
Parent* tmp;
for( int i = 0; i < this->vtParent.size(i); i++ ){
// PROBLEM with this line because I don't write the code of
// function 'virtual Parent* Parent::Intersection(Parent anotherParent)'
*tmp = this->vtParent.at(i)->Intersection(anotherParentVector.getParentVector().at(i));
result->getParentVector.push_back(tmp);
}
}
I don't write the code of function 'virtual Parent* Parent::Intersection(Parent anotherParent)', so I can not execute the code above. Some one has an idea how to resolve this problem ?
// Here, the idea is I want to call function 'Numeric* Intersection(Numeric anotherNumeric)' or 'Symbolic* Intersection(Symbolic anotherSymbolic)'
// FINISH, thanks for all yours suggestion.
Your child classes are changing the return type and parameter type of the Intersection function, which essentially makes it a new function and NOT one that behaves polymorphically. The functions must have the same function signature.
3 issues in your code:
when store value in STL container, copy constructor will be called, subclass object will be sliced. so if you want to keep polymorphism of some object, pointer/smart_pointer or reference only can be used. in container scenario, pointer/smart_pointer is suitable.
std::vector<Parent*> vtParent
parameter type must be identical between base class and derived class.
issue of return type see enter link description here
class Parent{
public:
...
virtual Parent& Intersection(Parent anotherParent);
}
class Symbolic : public Parent{
public:
...
symbolic& Intersection(Symbolic anotherSymbolic)
{
...
}; // do intersection with another object symbolic
}
You are facing object slicing when you push_back an object of Symbolic or Numeric into the vector if you are not using C++11. In case of C++11 system will use move symantic to fill the vector if your class definition is adaptable for it, either you should define move constrctor and move assignment operator or depends on default of those functions.
To overcome the object slicing, you can use
std::vector<Parent*> vtParent;
in place of use std::vector<Parent> vtParent;
And virtual functions should keep the same function returns as observed by Ami Tavory and Adam Finley. But in your case you can use as follows since your return types are covariant .
virtual Parent* Intersection(Parent anotherParent);
symbolic* Intersection(Symbolic anotherSymbolic);
Numeric* Intersection(Numeric anotherNumeric);
And please note the virtual destructor is missing from your base class.
Edit:
You can simplify your ParentVector::Intersection() as follows.
std::vector<Parent*> Intersection(ParentVector anotherParentVector){
std::vector<Parent*> result;
Parent * tmp;
std::vector<Parent*>::iterator it= vtParent.begin();
for( ; it != vtParent.end(); ++it){
tmp= it->Intersection(anotherParentVector.getParentVector().at(i));
result->getParentVector.push_back(tmp);
}
return result;
}
Yes this doesnt call delete on things but just to show you the route you need to take
#include <iostream>
#include <vector>
#include <memory>
class Parent{
public:
virtual Parent* Intersection() = 0;
};
class Numeric : public Parent{
public:
Parent* Intersection()
{
std::cout << "\nNumeric!";
return new Numeric;
} // do intersection with another object numeric
};
// class Symbolic
class Symbolic : public Parent{
public:
Parent* Intersection()
{
std::cout << "\nSymbolic!";
return new Symbolic;
} // do intersection with another object symbolic
};
class ParentVector{
public:
ParentVector()
{
vtParent.push_back(std::make_unique<Symbolic>());
vtParent.push_back(std::make_unique<Numeric>());
}
void print()
{
for (const auto& e : vtParent) {
e->Intersection();
}
}
ParentVector Intersection(ParentVector anotherParentVector);
private:
std::vector<std::unique_ptr<Parent>> vtParent; // vector stock object Parent (Numeric or Symbolic)
};
int main()
{
ParentVector pvec;
pvec.print();
std::cout << '\n';
system("PAUSE");
return 0;
}
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.
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;
}
What are the ways in C++ to handle a class that has ownership of an instance of another class, where that instance could potentially be of a number of classes all of which inherit from a common class?
Example:
class Item { //the common ancestor, which is never used directly
public:
int size;
}
class ItemWidget: public Item { //possible class 1
public:
int height;
int width;
}
class ItemText: public Item { //possible class 2
std::string text;
}
Let's say there is also a class Container, each of which contains a single Item, and the only time anyone is ever interested in an Item is when they are getting it out of the Container. Let's also say Items are only created at the same time the Container is created, for the purpose of putting them in the Container.
What are the different ways to structure this? We could make a pointer in Container for the contained Item, and then pass arguments to the constructor of Container for what sort of Item to call new on, and this will stick the Items all in the heap. Is there a way to store the Item in the stack with the Container, and would this have any advantages?
Does it make a difference if the Container and Items are immutable, and we know everything about them at the moment of creation, and will never change them?
A correct solution looks like:
class Container {
public:
/* ctor, accessors */
private:
std::unique_ptr<Item> item;
};
If you have an old compiler, you can use std::auto_ptr instead.
The smart pointer ensures strict ownership of the item by the container. (You could as well make it a plain pointer and roll up your own destructor/assignment op/copy ctor/move ctor/ move assignment op/ etc, but unique_ptr has it all already done, so...)
Why do you need to use a pointer here, not just a plain composition?
Because if you compose, then you must know the exact class which is going to be composed. You can't introduce polymorphism. Also the size of all Container objects must be the same, and the size of Item's derived classes may vary.
And if you desperately need to compose?
Then you need as many variants of Container as there are the items stored, since every such Container will be of different size, so it's a different class. Your best shot is:
struct IContainer {
virtual Item& getItem() = 0;
};
template<typename ItemType>
struct Container : IContainer {
virtual Item& getItem() {
return m_item;
}
private:
ItemType m_item;
};
OK, crazy idea. Don't use this:
class AutoContainer
{
char buf[CRAZY_VALUE];
Base * p;
public:
template <typename T> AutoContainer(const T & x)
: p(::new (buf) T(x))
{
static_assert(std::is_base_of<Base, T>::value, "Invalid use of AutoContainer");
static_assert(sizeof(T) <= CRAZY_VAL, "Not enough memory for derived class.");
#ifdef __GNUC__
static_assert(__has_virtual_destructor(Base), "Base must have virtual destructor!");
#endif
}
~AutoContainer() { p->~Base(); }
Base & get() { return *p; }
const Base & get() const { return *p; }
};
The container requires no dynamic allocation itself, you must only ensure that CRAZY_VALUE is big enough to hold any derived class.
the example code below compiles and shows how to do something similar to what you want to do. this is what in java would be called interfaces. see that you need at least some similarity in the classes (a common function name in this case). The virtual keyword means that all subclasses need to implement this function and whenever that function is called the function of the real class is actually called.
whether the classes are const or not doesn't harm here. but in general you should be as const correct as possible. because the compiler can generate better code if it knows what will not be changed.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class outputter {
public:
virtual void print() = 0;
};
class foo : public outputter {
public:
virtual void print() { std::cout << "foo\n"; }
};
class bar : public outputter {
public:
virtual void print() { std::cout << "bar\n"; }
};
int main(){
std::vector<outputter *> vec;
foo *f = new foo;
vec.push_back(f);
bar *b = new bar ;
vec.push_back(b);
for ( std::vector<outputter *>::iterator i =
vec.begin(); i != vec.end(); ++i )
{
(*i)->print();
}
return 0;
}
Output:
foo
bar
Hold a pointer (preferably a smart one) in the container class, and call a pure virtual clone() member function on the Item class that is implemented by the derived classes when you need to copy. You can do this in a completely generic way, thus:
class Item {
// ...
private:
virtual Item* clone() const = 0;
friend Container; // Or make clone() public.
};
template <class I>
class ItemCloneMixin : public Item {
private:
I* clone() const { return new I(static_cast<const I&>(*this); }
};
class ItemWidget : public ItemCloneMixin<ItemWidget> { /* ... */ };
class ItemText : public ItemCloneMixin<ItemText> { /* ... */ };
Regarding stack storage, you can use an overloaded new that calls alloca(), but do so at your peril. It will only work if the compiler inlines your special new operator, which you can't force it to do (except with non-portable compiler pragmas). My advice is that it just isn't worth the aggravation; runtime polymorphism belongs on the heap.