If I have the following classes:
class A
{
...
}
class B
{
...
}
class C : public A, public B
{
...
}
and somewhere I detect that the pointer of class B that I have actually points to a class C, but a function requires a pointer to class A, what can I do to get that pointer to class A?
If you know for certain that you have a B* that points to a C object, you can use a pair of static_casts:
B* bp = new C();
C* cp = static_cast<C*>(bp);
A* ap = static_cast<A*>(cp);
The only way to cast across the inheritance hierarchy is to use dynamic_cast, which requires that the type is polymorphic (that is, your class must have at least one virtual member function; since your base class destructors should be virtual, this usually isn't a problem):
B* bp = new C();
A* ap = dynamic_cast<A*>(bp);
dynamic_cast has the added benefit that if it fails (that is, if bp doesn't actually point to a C), it returns NULL. It has the disadvantage of a slight performance cost (static_cast is effectively free at runtime).
The code
class A
{
};
class B
{
};
class C : public A, public B
{
};
int main() {
C c;
A *a = &c;
}
is valid since C is already an A, so the assignment is valid.
If C inherits from A as you have shown, then a C* pointer should be implicitly convertible to an A* pointer. Is it possible that you haven't included the declaration of class C, so that the compiler isn't aware of this inheritance relationship? Or that there is actually a different inheritance relationship than that given in your question? Some code would be helpful in diagnosing this problem.
Edit
Based on the updated version of your question:
// Converts b to type A*, but only if it is actually
// of type C; otherwise, returns NULL
A* convertBtoAviaC(B* b) {
C* c = dynamic_cast<C*>(b);
return c; // note may be NULL, if b is not a C
}
Related
#include <iostream>
struct A {
virtual void a() {
puts("A");
}
};
struct B {
virtual void b() {
puts("B");
}
};
struct C {
virtual void c() {
puts("C");
}
};
struct D : public A, public B, public C {
virtual void c() {
C::c();
puts("cd");
}
};
int main() {
A* obj = new D;
obj->a();
B* b = (B*)obj;
b->b();
C* c = (C*)obj;
c->c();
return 0;
}
I have this code where I have non virtual multiple inheritance. However, it seems to call the wrong virtual function when I call the functions in the main function.
Instead of outputting:
A
B
C
cd
It outputs:
A
A
A
What puzzles me is that when I change the code to doing this:
B* b = (B*)(D*)obj;
b->b();
C* c = (C*)(D*)obj;
c->c();
It outputs what I would expect (see above). Afaik doing a double pointer cast like this wouldn't effect anything and would be optimized out by the compiler. But it seems to be changing what virtual function is being called.
Can someone explain why this would change what virtual function is being called?
Notes:
I printed the pointers at each step, they are the same.
I want to avoid using dynamic_cast (although it does work) as it's too slow for what I need it to do.
Can someone explain why this would change what virtual function is being called?
Generally, a C-style cast between pointer types won't change the value of the pointer and so will have no effect. There is, however, one exception.
A cast between a class and a parent or child class can change the value of the pointer. For example:
class A
{ int a; };
class B
{ int b; };
class C : public A, public B
...
Now, a pointer to an instance of class A will probably have the same value as a pointer to its a member and a pointer to an instance of class B will probably have the same value as a pointer to its b member. A pointer to an instance of class C can't have the same value as a pointer to both its A::a and its B::b members since they're distinct objects.
A function expecting a B* can be passed a C* since a C is a B. Similarly, a function expecting an A* can be passed a C* for the same reason. But at least one of these will require a value change to the pointer.
So casts between these types will change the values, the others are all no-ops.
Of course, all of this is UB. You are casting between unrelated types and then dereferencing them.
I want to avoid using dynamic_cast (although it does work) as it's too slow for what I need it to do.
That seems very hard to believe.
I am working on a simple C++ (under Linux) project, which will have pointers to objects. I have class A, class B which extends A, and class C which extends B. Class C has a method (test) that does not exist in A or B.
Is is possible to have a single pointer 'p' that can point to an object of type A, B, and C ? How would I define that pointer?
Secondly, since a.test() doesn't exist, but c.test() does, can my generic pointer 'p' call p->test() ? Will this compile? What if at run time p points to an object of class A and I call p->test()? Is that a runtime error?
Is is possible to have a single pointer that can point to an object of
type A, B, and C ?
I assume you mean "that can either point to an A object or to B object or to a C object", right?
Yes, you can have such a pointer.
How would I define that pointer?
A*
A base-class pointer can point to objects of derived classes.
Secondly, how would I call methods of the object if the pointer can
point to A/B/C classes?
You define a virtual function in A and override it in B and C. Then, when you call the method through your A*, the language will perform dynamic dispatch, i.e. it will automatically call the right method depending on whether your A* points to an A, to a B or to a C.
Do I need to cast them before calling the methods?
No. That would pretty much defeat the purpose of virtual functions.
Here is a complete example:
#include <iostream>
class A
{
public:
virtual ~A() {} // not really needed in this program,
// but almost always needed in real code
// when a class has a virtual function
virtual void method() { std::cout << "A::method\n"; }
};
class B : public A
{
public:
virtual void method() override { std::cout << "B::method\n"; }
};
class C : public A
{
public:
virtual void method() override { std::cout << "C::method\n"; }
};
int main()
{
A a;
B b;
C c;
A* ptr = &a;
ptr->method();
ptr = &b;
ptr->method();
ptr = &c;
ptr->method();
}
Output:
A::method
B::method
C::method
I would like the class A to inherit from the class B without A having is own instantiation of B
The idea would be to create an B object on the heap (using B new) and give the pointer to A.
A would afterwards use this object to solve inheritance.
This is an example of what I would like to do:
B* b = new B();
b->myBmethode();
{
A(b);
A.myBmethode();
} // A destroyed
b->myBmethode();
delete b;
No, it is impossible (if I understood your question correctly).
3.7.5
The storage duration of member subobjects, base class subobjects and
array elements is that of their complete object
If B was created outside of A, B won't be deleted automatically after A get deleted,unless u do it explicitly,
Create an interface IA, let both A and B implement that interface. For B, just delegate all the real implementation to B.
The lifecycle of B depend on your design. When would u like it to be destroyed? You can also make B singleton if it make sense.
class IA {
virtual doA() = 0;
}
class A: public IA {
virtual doA();
}
class B: public IA {
B(A&a);
virtual doA(){
a.doA();
}
private:
A&a;
}
//init
A* a = A::getInstance();
B *b = new(*a) ;
b->doA();
You cannot inherit from a reference, but with something like this you can get half-way there:
#include<functional>
...
struct A : std::reference_wrapper<B>{
// using std::reference_wrapper<B>::reference_wrapper; // inherit constructor
};
https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
I have a class D that extends B which extends A. I now want to add a class C that has exactly the same interface as B but provides a different implementation. So I design it as the following:
This is not exactly what I want, as I only need an instance of D to either extend B or C and not both, however, this is only determined at runtime. The problem with the design above is of course that if I call a method in D which is implemented both in B and C, its ambiguous.
So what I would like to have is to create an instance of either B or C at runtime and then cast it into D. Every time an instance of D calls an inherited method it should use the one of its original object.
Do I need to fiddle with typeid and if/else around each method call or is there a more elegant way to do this?
class A{
virtual f1();
virtual f2();
}
class B : public virtual A{
f1();
f2();
f3();
}
class C : public virtual A{
f1();
f2();
f3();
}
class D : public B, public C{
f4(){f1(); f3)};
}
...
D* d = new D();
E* e = new E(d);
e->d->f1();
e->d->f4();
Instances of D are then passed to another class (E) which does stuff with D and therefore, I cannot modify the interface of D.
I think you're having inheritance the wrong way around, what you do is define all the methods that you want to call on what you call class D as virtual methods in class A, class B and C both have their own implementation of those methods.
Then you use a data structure of type A*, fill that with pointers to objects of type B and C and you call the methods that you need to call on all the objects in the data structure that contains pointers of type A*, the vtable mechanism will then make sure that the implementation of class B or C is used depending on what the actual object's type is.
See What is the difference between a concrete class and an abstract class?
It sounds like you just want
class A{
virtual void DoMagic() = 0;
};
class B{
virtual void DoMagic(){};
};
class D{
virtual void DoMagic(){};
};
...
bool INeedB = true;//or false
A* a;
if(INeedB){
a= new B();
}else{
a = new C();
}
a->DoMagic(); // will call the appropriate method based on the value of INeedB;
Unless D actually has behavior of its own? Then you can look at decorator pattern, and make D the decorator of an instance of B or C.
Edit: Your D class doesnt need to inherit any of A B or C at all.
class D{
D(A* aObj):a(aObj){}
void f3(){ a->f1();a->f2();}
A *a;
};
Replace A *a in above example with D d
C++ is a statically-typed language. Whatever you do with type declaration is elaborated at compile time, hence the inheritance graph of D cannot be defied at runtime.
What you probably need is to have A as a polymorphic base (with all relevant method virtual, included the destructor) for both B and C (concrete implementation of that), and D an "owner of an A", by containing an A* thet will be assigned at D construction to a new B or new C depending on input.
D destructor will call delete A, and now you have to decide about copy and assignment.
My suggestion is not to use an A*, but a std::unique_ptr (will make the owned object movable between D-s) or std::shared_ptr.
In case you need each D to have its own A, then let A to have a clone method (overridden in B and C, to return a new B and new C respectively) and call it in D's copy ctor and assign operator.
It seems like D doesn't need to inherit from A (or B or C) at all. Instead it just needs to call function in either an instance of B or an instance of C.
You can implement it something like this:
class A
{
public:
virtual void f1();
virtual void f2();
};
class B : public A;
class C : public A;
class D
{
A* b_or_c;
public:
D(A* a_pointer)
: b_or_c(a_pointer)
{}
void f3()
{
b_or_c->f1();
b_or_c->f2();
}
};
Can be used like this:
B b; // An instance of B
C c; // An instance of C
D d1(&b);
D d2(&c);
d1.f3(); // Will cause `f1` and `f2` in the object `b` to be called
d2.f3(); // Will cause `f1` and `f2` in the object `c` to be called
Compiling f works, but compiling g fails with an error.
Why does this happen?
class A {
public:
A() {}
};
class B : public A {
public:
B() {}
};
void f() {
A* a = new A();
B* b = static_cast<B*>(a);
}
void g() {
A* a = new A();
B* b = a;
}
A static_cast forces a conversion that is potentially unsafe.
B* b = static_cast<B*>(a);
This would be valid if a pointed to an A object that actually was the base class sub-object of a B object, however it doesn't. The cast forces the conversion.
B* b = a;
There is no cast here and there is (correctly) no implicit conversion allowed from base class pointer to derived class pointer. A pointer to a derived class can always be converted to a pointer to a base class because a derived class object always contains a base class sub-object but not every base class instance is a sub-object of a particular derived class type.
Well, yeah. Doing:
B* b = new A();
Is unsafe. You end up with a B pointer to an A object; you never construct the B portion of the object; your object is "sliced".
On the other hand...
A* a = new B();
...would be fine.
You are trying to convert a pointer from A* to B*. I am not sure what you are trying to achieve. But since B* is derived from A* and not the other way around this is not valid. Maybe you want to do something like this:
int main()
{
///The above code compiles while if I replace above two line in main with below assignment it gives error.
A *a=new A();
A * b=new B();
}
Yes, it does give an error if you want to assign a base class to a derived class pointer type. No, it doesn't give an error if you explicitly cast the pointer type, because in C++ you are allowed to shoot yourself in the foot if you so desire.
What exactly is baffling you, or what did you expect to achieve with your code?
A base class cannot be implicitly converted to a derived class. Just consider this
class A {
public: int x;
};
class B : public A {
public: int y;
};
B* b = new A; // assume it works, so 4 bytes is allocated and initialized.
b->y; // bam! accessing unallocated region.