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.
Related
For example, I have an abstract base class A and B. A has a virtual method as follows
class A
{
public:
virutal void f(B& b) = 0;
};
For class A1
class A1 : public A
{
public:
void f(B& b) override { b.f(A1); }
};
And thus for B, it needs a virtual method f(A1)
class B
{
public:
virtual void f(A1& a) = 0;
};
And in class B1 : public B, the virtual method is implemented. The problem is that when another class A2 : public A is added, I have to add a virtual method virtual void f(A2& a) = 0 in class B, which I think it breaks the code because I don't know if A2 even A1 is added or not when I design class B. How to avoid it but implement the equivalent requirements? Any C++ feature can be used even with templates.
Unfortunately, there's no such thing as a virtual template function in C++ (this is what I believe you're trying to accomplish, after parsing your question).
The closest, and the least ugly solution I can think of, is to have the virtual function in base class B take the base class A as a parameter:
class B
{
public:
virtual void f(A& a) = 0;
};
B1 overrides that, and then uses dynamic_cast to cast its parameter to an instance of A1.
In this manner, you can continue an define each Ax and Bx pair of derived classes, without having to change the API interface in the base class, between the two hierarchies.
A bit ugly, but the question states "any C++ feature can be used", and dynamic_cast certainly qualifies under that requirement.
Consider the following code:
class A {
};
class B : public A {
};
class C : public B{
public:
C() : A() {} // ERROR, A is not a direct base of B
};
In this case GCC (4.8.1, C++99) gives me the correct error (I understand this behavior):
prog.cpp:12:8: error: type ‘a’ is not a direct base of ‘c’
However if the inheritance between b and a is virtual, this does not happen:
class A {
};
class B : virtual public A {
};
class C : public B{
public:
C() : A() {} // OK with virtual inheritance
};
Why does this work?
Is A now considered a direct base to C by the compiler?
In general, because this is how C++ tries to resolve the diamond inheritance problem http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem (whether or it is a good or bad solution is left as an exercise to the reader).
All inheritance is a combination of an is-a and a has-a relationship...you must instantiate an instance of the parent. If you have the following classes:
class a;
class b : a;
class c : a;
class d : b,c;
Then you've instantiated an a for each b and c. d will not know which a to use.
C++ solves this by allowing virtual inheritance, which is high-overhead inheritance that allows b and c to share the same a if inherited in d (it is much more complicated than that, but you can read up on that on your own).
The most derived type in the chain needs to be able to override the instantiation of the shared class to control disparities in the way that the shared class is inherited in the parent classes. Take the following example:
class a {int x; public: a(int xx) {x=xx;} int get_x() {return x;}};
class b : public virtual a { public: b(): a(10){}};
class c : public virtual a { public: c(): a(15){}};
class d : public virtual b, public virtual c {public: d() : a (20) {}};
int main() {
d dd;
std::cout << dd.get_x() << std::endl;//20, d's constructor "wins"
return 0;
}
If d did not define what a was instantiated as, it would have definitions for conflicting instantiations (from b and c). C++ handles this by forcing the most derived class in the inheritance chain to instantiate all parent classes (the above would barf if d did NOT explicitly instantiate a, though if a supplied a default constructor that could be implicitly used) and ignoring all parent instantiations.
Why does this work?
According to the standard (10.1.4 in the FIDS), "for each distinct baseclass that is specified virtual, the most derived object shall contain a single base class subobject of that type".
Virtual base is shared between all classes that derive from it for the instance of the object. Since a constructor may only be called once for a given instaniation of an object, you have to explicitly call the constructor in the most derived class because the compiler doesn't know how many classes share the virtual base. This is because the compiler will start from the most base class's constructor and work to the most derived class. Classes that inherit from a virtual base class directly, will not, by the standard, call their virtual base classes constructor, so it must be called explicitly.
From N3337, 12.6.2
Initializing bases and members
In the definition of a constructor for a class, initializers for direct and virtual base subobjects and non-static data members can be specified by a ctor-initializer, which has the form
Perhaps someone who has better version of Standard can verify this.
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);
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.)
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.