How to instantiate array of derived classes - c++

I am trying to set an array of base class and derived classes in another class. For example, I have base class:
class Base{
public:
Base() {};
Base(float kv) : param(kv) {}
~Base() {};
float getParam() { return param; }
void setParam(bool kv) { param= kv; }
protected:
float param;
};
and derived classes like:
class Derived1: public Base{
public:
Derived1() {};
Derived1(float kv) : Base(kv) {}
~Derived1() {};
};
Now, in another class I have an array of Base type.
class Hive{
public:
Hive() {};
Hive(...) : ... {}
~Hive() {};
...
float getSomethingFromArray();
...
void setB();
protected:
...
Base *b[7];
};
Now, setB() instantiate array, like:
b[0] = new Derived1();
but when I try to access method of b[0] it would't work.
when I call method like:
b[0].setParam(i);
Compiler reports this error
IntelliSense: expression must have class
type c:\users\miller\documents\visual studio
2010\projects\hello\hello\objekat.h 139 2 hello

but when I try to access method of b[0] it would't work. Any ideas why?
b[0] is a Base*. The compiler doesn't know whether the actual type of the object it points to is Base, Derived1 or Derived42, that's why it will only let you call methods from Base on it - because those are the only ones that it can guarantee exist.
I'm guessing you're trying to call methods from Derived1 on it:
b[0] = new Derived1();
//...
b[0]->getSomethingFromArray();
but note that your code could easily be replaced by:
b[0] = new Base();
//...
b[0]->getSomethingFromArray();
what now? To get this to work, you can use casts and cast b[0] to the type you need (provided you're sure of it). If your classes are polymorphic, you can use dynamic_cast, which also does checks to make sure you're casting to the right type (research this).
Or, you could simply take advantage of polymorphism (only if it makes sense in your particular case).

Your mistake is very simple, to call method via pointer you must use -> operator - not dot .:
Not this way:
b[0].setParam(i);
But in this way:
b[0]->setParam(i);

Related

how to cast to "this" type from base to derived class

I want to retrieve the initial type in the base class A because the method encodeMsg() will have tasks that are related to the derived type
#include "stdafx.h"
#include <iostream>
struct base {
};
struct derive : base {
};
class A{
public:
A(){}
virtual void encode() {
encodeMsg(_bStruct);
// here I want to cast base to derive but I don't know how I tried
// static_cast<decltype(this)>(_bStruct) but it seems doesn't work
}
virtual void setStruct(base* bStruct) {
_bStruct = bStruct;
}
private:
virtual void encodeMsg(base* bStruct) = 0;
protected:
base* _bStruct;
};
class B : public A {
public:
B(){}
void encodeMsg(base* bStruct) {
derive* _dStruct = static_cast<derive*>(bStruct);
// ..
// stuff within dervied struct
_bStruct = static_cast<base*>(_dStruct); // turn back to base struct
}
};
int main() {
B b;
base* _bStruct = new derive();
b.setStruct(_bStruct);
b.encode();
return 0;
}
The question makes no sense.
In your code, the only thing you could do with the pointer, if you could create it, is access members known to be in the base class. But you can do that already without the pointer. So what purpose does the pointer serve?
If you want to one thing if it's a derived1 and something else if it's a derived2, then you need to use one piece of code for the derived1 case and one piece of code for the derived2 case.
If you want to do the same thing regardless of what derived type it is, there is no need for the cast you seek. The code in this function will be the same regardless of what the derived type is.
If you want code that only works if the derived type is some specific type, use a dynamic_cast to a pointer to that type and write the specific code. If you want code that works regardless of the derived type, use a pointer to an instance of the base class.
Update:
To access members not in base but in a derived1, use this code:
virtual void encode() {
derived1* d1 = dynamic_cast<derived1*>(bStruct);
if (d1 != nullptr)
{
// here you can access d1->whatever
}
}

c++ Multiple inheritance and casting

I have the following classes :
class A { };
class B {
public:
B(){}
virtual ~B(){};
};
class B1 : public B{
public:
B1(){}
virtual ~B1(){};
};
class B2 : public B{
public:
B2(){}
virtual ~B2(){};
};
class C1 : public A, public B1{
public:
C1(){}
virtual ~C1(){};
};
class C2 : public A, public B2{
public:
C2(){}
virtual ~C2(){};
};
I want to know if an object of type B is also of type A :
B*b = new C1(); // or new B, or new C2 ...
if(dynamic_cast<A*>(b))
{
...
Is my dynamic_cast the correct way do that (it compiles and it runs)?
Thank you.
To be able to use dynamic_cast all parents of the object needs to be polymorphic. I.e. you need to add at least one virtual function to the A class (like the destructor).
Once you fix that then your dynamic_cast is fine.
Class A is different than Class B in the C++ type system. Since they are both empty, they should be same however they are instatiated in memory. Even empty classes have the identity property.
dynamic_cast<new_type> (expression) commonly is used as: dynamic_cast<derived_type> (myBase). In this case "If expression is a pointer or reference to a polymorphic type Base, and new_type is a pointer or reference to the type Derived a run-time check is performed:" see cppreference.com search for dynamic_cast. This allows you to cast the base class back down to the derived class. The programmer must know that the derived class exists.

Is it unsafe to store derived object to void*, then cast base object out of it?

For example:
class Base1 {};
class Base2 {};
class Derived: publid Base1, public Base2 {};
// object is stored on a void* slot
void* void_slot = new Derived();
// ... many decades after ...
//object is fetched from the void* slot
Base2* obj = (Base2*) void_slot;
obj->some_base2_method();
I think it is probably unsafe. Does dynamic_cast<> solve this issue?
Base2* obj = dynamic_cast<Base2*> void_slot;
More backgrounds:
I'm working on calling C++ library from Perl. When you construct an C++ object, it is stored in the integer slot of a Perl value (the IV value of a SV), which is like a void*; and when you call methods, the object pointer is cast from IV, and the corresponding C++ method is called using the object pointer. Thus I guess it could be problematic, as the pointer to base type can be different with the pointer to derived type, especially when there are multiple inheritance.
I've posted a similar question on PerlMonks, but did not get much response from there. So I ask it here, from the aspect of C++.
Yes it is unsafe, but will probably cause no errors in your example due to the empty base optimization. Consider instead the following example:
class Base1 { int b1; };
class Base2 { int b2; };
class Derived : public Base1, public Base2 { int d; };
The memory layout for an object of type Derived will probably look like this:
0123456789AB
[b1][b2][ d]
^ begin of Derived
^ begin of Base1
^ begin of Base2
Now, a pointer to Derived and to Base1 will have the same numerical value, but one to Base2 will be different. To change the numerical value appropriately, the compiler has to know that you are converting a Derived* to a Base2*. This is not possible when casting it to void* in between, since the value of the void* could just as well have come from a Base2*.
In fact, a conversion sequence like static_cast<T*>(static_cast<void*>(x)) is exactly how reinterpret_cast<T*>(x) is defined. And you would not assume that reinterpret_cast is safe to randomly use an arbitrary types - would you?
What about dynamic_cast?
While one might believe that dynamic_cast might help here, it is in fact not even applicable! Since dynamic_cast is supposed to use run time type information to guarantee that a cast is possible, its target needs to be a pointer (or reference) to a class type with at least one virtual member. In this case, the target is not even a pointer to a complete type, but to void.
How to deal with the conundrum?
No matter what you do afterwards you must retrieve the same type of pointer that you stored (with a sole exception for interpreting your object as a char array). The obvious solution would be, to either always store a pointer to a common base class like
void* void_slot = static_cast<CommonBase*>(input);
CommonBase* output = static_cast<CommonBase*>(void_slot);
or to use an intermediate class that knows which kind of pointer you are talking about
struct Slotty {
enum class type_t {
Base1,
Base2,
Derived
} type;
void* ptr;
Slotty(Base1* ptr) : type(type_t::Base1), ptr(ptr) { }
Slotty(Base2* ptr) : type(type_t::Base2), ptr(ptr) { }
Slotty(Derived* ptr) : type(type_t::Derived), ptr(ptr) { }
};
void* void_slot = static_cast<void*>(new Slotty(input));
Slotty* temp = static_cast<Slotty*>(void_slot);
switch(Slotty.type) {
case Slotty::type_t::Base1:
/* do sth with */ static_cast<Base1*>(temp.ptr);
break;
case Slotty::type_t::Base2:
/* do sth with */ static_cast<Base2*>(temp.ptr);
break;
case Slotty::type_t::Derived:
/* do sth with */ static_cast<Derived*>(temp.ptr);
break;
}
If you have complete control over your classes, just create a single virtual root base. Cast to that first before you cast to void *, then cast back to that first. Then you can use dynamic_cast to cast to whatever derived type you want:
struct Root {
virtual ~Root() {}
};
struct Base1 : virtual public Root { };
struct Base2 : virtual public Root { };
struct Derived1 : public Base1, public Base2 { };
struct Derived2 : public Derived1 { };
int main() {
Derived1 *d1 = new Derived1;
Derived2 *d2 = new Derived2;
void *vp = static_cast<Root *>(d1);
Derived1 *d11 = dynamic_cast<Derived1 *>(static_cast<Root *>(vp));
vp = static_cast<Root *>(d2);
Derived2 *d22 = dynamic_cast<Derived2 *>(static_cast<Root *>(vp));
delete d1;
delete d2;
}
EDIT: Apparently the classes must be polymorphic and you must use dynamic_cast, so put a trivial virtual destructor in Root.

C++ change member type in derived class

I have a class Base1 that contains an array of objects of a different class Base2. I would like to have a derived class Derived1 that inherits everything from Base1 except the array is of type Derived2 (which is a derived class of Base2). For example, something like this:
class Base2{
int a2;
};
class Derived2: public Base2{
int b2;
};
class Base1{
Base2* list;
};
class Derived1: public Base1{
Derived2* list;
};
My understanding is that in the above example, an object of Derived1 would actually have TWO arrays:
list
and
Base1::list
which I don't want.
The idea is that all the functionality of Base1 should still work for a Derived1 object since Derived2 "is a" Base2. It would be really dirty, but I guess I could just delete[] the Base1::list array in the Derived1 constructor.
Does anyone see a solution to this? It seems like something that would happen frequently, and I cannot believe a simple solution does not exist. Would using templates work? My thought was no, since all the functionality in Base1 and Derived1 need to know that they are dealing with Base2 and Derived2 objects, respectively.
What do you expect to happen when someone downcasts a Derived1 class to Base1? It will crash when list is used after you sabotage the base class. The best thing is to continue to use the base class's list, and make sure only objects of type Derived2 are put in the list. If the content of the list can't be externally modified, that would work and be safe.
Yes, I know there's a lot more to say about this but let's take it one step at a time.
What you are trying to do, in general case, seems dangereous, but I assume you know the risks ;)
I can suggest two solutions:
Option 1:
You can hide the actual pointer in a protected section and provide an access function.
class Base1 {
protected:
void *ptr
public:
Base2 *list() {return (Base2*)ptr;}
};
class Derived1 : public Base1 {
public:
Derived2 *list() {return (Derived2*)ptr;}
};
Basically, the Base2::list will be hidden by the Derived2::list. Note, you cannot make them virtual and benefit from the virtuality. The return type has to be known at compile-time.
Option 2:
You can use templated base class.
template <typename T>
class List {
public:
T *list
//implement all functionality which is common, regardless of the type T
};
class Base1 : public List<Base2> {
//specifics for Base2 type
};
class Derived1 : public List<Derived2> {
//specifics for Derived2
};
Note that in this construct, Base1 and Derived1 are not directly related, but have a common ancestor instead.
I'd remove the array of Base2 from Base1, and create a new class with the list:
class Base2{
int a2;
};
class Derived2: public Base2{
int b2;
};
class Base1{
};
class Base1WithList : public Base1{
Base2* list;
};
class Derived1: public Base1{
Derived2* list;
};
I dont think there exists anything simple that solves your problem.
I would have used one of the following ways -
OPTION 1
Hide the Base2* list (in base1 class) by making it private, and save it getting inherited by the derived class (derived1). And of course, define a getter function in base1 class to access the list.
OPTION 2
Just change the type of list in base1 class to (a pointer to) Derived2 , and rely on the fact that a pointer to a derived class is type-compatible with a pointer to its base class.
OPTION 3
Forget inheritance and use templates. You will just need to specify the type (Base2* or Derived2*) while instantiating an object, and life will be beautiful again.
The question comment from #ildjarn gave me the solution to a similar problem:
class Base {
Base* children;
};
class Derived : public Base {
int answer;
public:
void give_answer() {
this->answer == 42;
for(auto child : this->children) {
// at this point `give_answer` is not defined for items of `children`
child->give_answer(); // -> error: ‘class Base’ has no member named ‘give_answer’
}
};
};
The solution is to introduce a virtual function into Base:
class Base {
Base* children;
public:
virtual void give_answer();
}
virtual void give_answer() = 0; would also work, making Base abstract.
(This example is a bit contrived, because why even have Base, but in my use case Derived is actually Derived<T>, and Base is a whole tree implementation.)

C++ design question

Suppose I have a class Base which has a member variable A* my_hash.
I also have class Extended which inherits from class Base. I also have a class B
which extends A.
class Base{
Base(): my_hash(new A) {}
//methods which use my_hash
protected:
A* my_hash;
};
class Extended:public Base{
//methods which use my_hash from A
//I cannot have a B* my_other_hash in this class
//I would like to substitute B* my_hash
//I cannot let Base create my_hash (of type A*) because that is not what I want.
};
I would like Extended to do the usual (i.e. use everything it inherits from A), except
and with one important difference, I want my_hash to be B* instead of A*.
Whenever something accesses my_hash, either via Extended's methods or Base's methods,
I would like the methods to be executed to be B*'s.
One thing to try:
I cannot have a method call (e.g. create_hash() in Base()) which I redefine in Extended.
This does not work as there seems no way to go back up to the class Extended when I create the hash.
I would not like Base to even know about B. How do I do this?
If the type of 'B' extends 'A', then you could set it up so that you pass the value for 'm_hash' through the constructor (you can also hide this constructor as protected so code that doesn't inherit from 'Base' can't extend it).
e.g.
class Base{
Base(): my_hash(new A) {}
//methods which use my_hash
protected:
A* my_hash;
Base(A* hash): my_hash(hash) {}
};
class Extended:public Base{
public:
Extended() : Base(new B) {}
};
Also, if you want new, specialised functions in 'B' that you can call from 'Extended', then you can either store that in another pointer or just cast 'my_hash' to type 'B*'.
You could make the Base class into a template on A:
template<typename T>
class Base{
Base(): my_hash(new T) {}
//methods which use my_hash
protected:
T* my_hash;
};
class Extended:public Base<B>{
...
};
A template might be the way to go here, as suggested by Autopulated. Another way to do it is in fact to have a B* my_other_hash (like you mention in the question), and then in B's ctor set my_other_hash to my_hash.
class Extended:public Base{
ExtendedBase(): Base() {
my_other_hash = my_hash;
}
}
Then you can access the A methods in Base and the A or B methods in Extended. Make sure to only delete one of them! In Base's dtor or outside the hierarchy if you manage the memory elsewhere.