This compiles fine, although I wouldn't want to try running it just yet. However ...
//class base;
//class derived;
//class derived : public base;
class base {};
class derived : public base {};
class other
{
public:
void func() {base1 = derived1;}
base* base1;
derived* derived1;
};
void main()
{
}
... moving the class other to above the definition of base and derived for which there is a similar thing I must do in a program of myne causes compile errors.
The obvious solution is to forward declare base and derived shown commented out at the top of the code, however this causes a can't convert between base* and derived* error. Attempting to forward declare including the inheritance information dosn't work either.
This should work. You need to move other up
BUT declare func below. That way func is able to "see" that derived is of type base.
e.g.,
class base;
class derived;
//class derived : public base;
class other
{
public:
void func();
base* base1;
derived* derived1;
};
class base {};
class derived : public base {};
void other::func() { base1 = derived1; }
There is no syntax for forward-declaring two classes and specifying that one inherits from the other. This is because inheritance can be complex (multiple and/or virtual), so the assignment base1 = derived1 might involve some arithmetic, and it's difficult/impossible for the compiler to generate that arithmetic when it only knows that derived inherits from base.
So, to solve your problem, you can make func not inline (see the answer from AbstractDissonance), or, if you absolutely need it to be inline, use reinterpret_cast:
class base;
class derived;
class other
{
public:
void func() {base1 = reinterpret_cast<base*>(derived1);}
base* base1;
derived* derived1;
};
This is bad because it is not guaranteed to work by the C++ standard, and it will almost certainly not work if you use multiple/virtual inheritance. Use this only if func has to be as fast as possible (i.e. inline), and if you don't need your code to be portable.
Related
I have been struggling with this kind of problem for a long time, so I decided to ask here.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
The method should return a dynamically created copy, or at least store the object on stack in some data structure to avoid "returning address of a temporary" problem.
The naive approach to implement the above method would be using multiple typeids or dynamic_casts in a series of if-statements to check for each possible derived type and then use the new operator.
Is there any other, better approach?
P.S.: I know, that the this problem can be avoided using smart pointers, but I am interested in the minimalistic approach, without a bunch of libraries.
You add a virtual Base* clone() const = 0; in your base class and implement it appropriately in your Derived classes. If your Base is not abstract, you can of course call its copy-constructor, but that's a bit dangerous: If you forget to implement it in a derived class, you'll get (probably unwanted) slicing.
If you don't want to duplicate that code, you can use the CRTP idiom to implement the function via a template:
template <class Derived>
class DerivationHelper : public Base
{
public:
virtual Base* clone() const
{
return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
}
};
class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };
An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.
How can I get derived class object from my generic interface pointer.
I do not want to type cast the generic interface in order to achieve above .
e.g:
class Base {}; // Has pure virtual functions and is my interface class
class Derived : public Base {}; // Additional functions .
Base *b = new Derived();
Now, I want to get derived pointer Derived *derived from b without casting.
How can I achieve this?
Your setup seems strange, I'd look for alternative options like returning Derived directly or moving the functions you need into base since you seem to need them.
If you still want to do that you could have something like:
class Derived; // Forward declaration
class Base {
public:
virtual Derived* as_derived() { return null; }
...
};
class Derived : public Base {
public:
Derived* as_derived() override { return this; }
};
Still, this looks like a hack and I would suggest casting instead. At least casting it's a common pattern and it will be easier for others to understand.
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.)
I have been struggling with this kind of problem for a long time, so I decided to ask here.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
The method should return a dynamically created copy, or at least store the object on stack in some data structure to avoid "returning address of a temporary" problem.
The naive approach to implement the above method would be using multiple typeids or dynamic_casts in a series of if-statements to check for each possible derived type and then use the new operator.
Is there any other, better approach?
P.S.: I know, that the this problem can be avoided using smart pointers, but I am interested in the minimalistic approach, without a bunch of libraries.
You add a virtual Base* clone() const = 0; in your base class and implement it appropriately in your Derived classes. If your Base is not abstract, you can of course call its copy-constructor, but that's a bit dangerous: If you forget to implement it in a derived class, you'll get (probably unwanted) slicing.
If you don't want to duplicate that code, you can use the CRTP idiom to implement the function via a template:
template <class Derived>
class DerivationHelper : public Base
{
public:
virtual Base* clone() const
{
return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
}
};
class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };
An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.
For instance I have code like that
class Base1
{
virtual void wonderFULL() = 0;
};
class Base2
{
// all this weird members
};
class Derived : public Base1, public Base2
{
// not so weird members
};
int main()
{
Derived Wonder;
magicFunction(&Wonder);
return 0;
}
void magicFunction(Base2 *ptr)
{
if (Base1 *b1 = dynamic_cast<Base1 *>(ptr))
b1->wonderFULL();
}
However wonderFULL is never executed due to impossibility to cast ptr to b1. Is it possible at all to perform such a conversion?
This
#include <iostream>
class Base1 {
public:
virtual void wonderFULL() = 0;
};
class Base2 {
public:
virtual ~Base2() {} // added so the code compiles
};
class Derived : public Base1, public Base2 {
virtual void wonderFULL() {std::cout << "wonderful\n";} // added so the code compiles
};
void magicFunction(Base2 *ptr) {
if (Base1 *b1 = dynamic_cast<Base1 *>(ptr))
b1->wonderFULL();
}
int main() {
Derived Wonder;
magicFunction(&Wonder);
return 0;
}
prints wonderful for me. My conclusion is that you're not showing the code necessary for your problem to reproduce.
Take (a copy of) your actual code and by removing uneccessary code step by step distill it until you derive at a self-contained (needs no other headers except from the std lib), compilable example that reproduces the problem. Very likely you will find the problem while doing so. However, if you don't, you have the perfect repro case to come back here and ask about.
You have some syntax errors, but your real problem is dynamic_cast won't work properly if your base classes don't have at least one virtual function.
If you make it look like:
class Base2
{
public:
virtual ~Base2() {}
// all this weird members
};
And then fix your other errors:
wonderFULL is private, and never defined.
magicFunction is declared after it is used.
Then everything works.
You can cast up the hierarchy then back down:
void magicFunction(Base2& ptr)
{
try
{
Derived& d = dynamic_cast<Derived&>(ptr);
Base1& b = dynamic_cast<Base1&>(d);
b.wonderFULL();
}
catch(const std::bad_cast&)
{ /* Cast failed */ }
}
Going by what I understand of the way some C++ compilers arrange the class hierarchy in memory it should be possible to cast from one base class to another, but you have to first cast to the derived class.
Therefore you would need to do something like:
Base1* b1 = dynamic_cast<Derived*>(ptr);
This casts the given pointer ptr to the derived class, and then it gets implicitly cast to its other base class pointer.
However another easier way to do this would be to just have a method in the Base2 class that returns a Base1 pointer, and the derived class can implement this itself without any tricky code. (The same function in Base2 can just return NULL if you don't want a pure virtual class).
I've found the problem. It was not about dynamic_casts. I was checking wrong object which was not inherited from abstract base. Thanks.