Switching between derived classes in C++ - c++

This is the closest things I could find to a possible duplication. However, the answers left me with questions still.
Here is a code sample:
class A {
A() {}
virtual void print() = 0;
}
class B : public A {
B() {}
void print() { printf("B"); }
}
class C : public A {
C() {}
void print() { printf("C"); }
}
int main() {
A** n;
n = new A*[4];
n[0] = new B;
n[1] = new C;
n[2] = new B;
n[3] = new C;
for(int i = 0; i < 4; i++)
n[i]->print();
printf("\n");
delete n[0];
delete n[1];
delete n[2];
delete n[3];
delete [] n;
}
With this bit of code you get "BCBC". Is there a way to change the derived class type without allocating a new object? Something like:
n[2] = (C*)n[2];
So that when you print the array out you now get "BCCC". I read in the linked post that having to do this is evidence of poor design. If that is the case, could that be explained? This seems like it would be a normal and frequent use case for object oriented design to me. Assume that all attributes are defined in the base class. The only difference in the classes are in the implementation of methods.
If C++ does not support changing an objects type like this at run time, what is the accepted way to achieve similar results?

Closest thing would be to implement in B and C constructors that will accept A(or A*) as input and copy any data need into new object. Then you should get something like this.
A* temp = n[2];
n[2] = new C(A);
delete temp;
But even better solution would be to create class that will hold data and A* pointing to a class implementing different ways of data manipulation.

The object pointed to by the pointer n[2] is a B object. It can't be magically changed into a C object. If you want a C object, you're going to have to create one. However, don't forget to delete the existing B object.
delete n[2];
n[2] = new C;

I don't believe that you can cast from class B to class C. Both of theses classes are also Class A, as in B is an A and C is an A however B is not a C and C is not an B. Either could be cast into A but this is a dangerous practice because of the slicing problem. In this case you have no data in the derived classes to be lost by casting so you aren't losing anything. However you don't need to cast a B or a C into an A in order to call the parent classes methods.
It would perhaps be possible to write a function that took a B object as input and returned a C object and a function that took a C object and returned a B object, but you would have to do all the work yourself manually converting one into the other.

You can't really change the type of object once it's created. But it doesn't mean you can't change behavior in run time. What you need to do is refactor your code.
class A;
class ImplA
{
public:
void print (A&) = 0;
};
class A
{
std::unique_ptr<ImplA> impl;
public:
A (ImplA* ia) : impl(ia)
{}
void print()
{
impl->print(*this);
}
void changeImpl (ImplA* ia)
{
impl.reset(ia);
}
};
This is of course using C++11's smart pointers, but the idea is the same regardless. You apply the fundamental theorem of software engineering: abstract the thing that changes.
I recommend you read up on design patterns. It will arm you with ideas to do the things you want without breaking the way OOP works.

Related

How to get subclass member in c++

For example I have two class
class A:
class A
{
private:
int a;
}
subclass B:
class B: private A
{
private:
char b;
public:
char getB();
}
code:
int main()
{
A* item = new B();
char b = (B)item->getB();
}
Should I use cast or should I redesign program if I need to do something like that? I dont want to use polymorphism.
The problems
1) B privately inherits from A. So only a B can cast a B* to an A*.
2) The priorities of your expression are same as (B)(item->getB()); So this will not compile as item is an A and A has no member getB().
3) It's better to use static_cast or dynamic_cast instead of the old C style cast.
The solution
1) Use public inheritance if you want to cast between your derived class and base class outside of the classes themselves.
2) Then use parenthesis:
char b = ((B*)item)->getB();
3) Or prefer more precise form:
char b = static_cast<B*>(item)->getB();
4) But when you're doing an downcast like this, it's at your own risk. If the A* pointer points to something else than a B or a class derived from B, then it's undefined behaviour.
As you consider having a polymorphic use of your type, you'd better have a virtual destructor so that you can delete item with the appropriate destructor (here it would use A's destructor instead of B's).
As soon as you've at least one virtual function, you can use the safer dynamic_cast:
if(dynamic_cast<B*>(item)) { // would be nullptr if item doesn't point to a B object
char b = dynamic_cast<B*>(item)->getB();
... // further processing of the char
}
else cout << "Ooops!"<<endl;
You should use dynamic_cast that safely converts pointers and references to classes up, down, and sideways along the inheritance hierarchy (cppreference.com):
dynamic_cast<B*>(item)->getB();
, instead of old style C cast:
((B*)item)->getB();
Edit:
You should use public inheritance to use dynamic_cast. For what purpose private inheritance was used? In your example it doesn't make much sense IMHO. Also using inheritance without virtual destructor is dangerous.

C++ function overload for classes

I have 3 classes
class A {
//...
}
class B : public A {
//...
}
And a class C:
#include "A.h"
#include "B.h"
class C
{
void method(A anObjOfA);
void method(B anObjOfB);
}
Now if I do
B* ptr = new B();
A* ptrToB = ptr;
c.method(*ptrToB);
It calls the method for Objects of type A, not the inherited actual type B.. How can I make sure the right function for the object deepest in the inheritence-tree is called, without actually knowing it's type at compile-time?
PS: I'm sure this is a noob question, for the life of me I can't find any results on this here, as everyone is busy understanding the "virtual" keyword, which is perfectly clear to me but is not the issue here.
Because resolving a function overload is done at compile-time. When you call the function it only sees the A part of the pointer, even though it could point to a B.
Perhaps what you want is the following:
class A
{
public:
virtual void DoWorkInC()
{
cout << "A's work";
}
virtual ~A() {}
};
class B : public A
{
public:
virtual void DoWorkInC()
{
cout << "B's work";
}
};
class C
{
void method(A& a)
{
a.DoWorkInC();
}
}
Let your class A, B have virtual function implemented in their respectivbe classes:
class A {
//...
public:
virtual void doTask();
};
class B : public A {
//...
public:
void doTask();
};
Ket A::doTask() and B::doTask() do respective tasks in object specific way, i.e. A::doTask() to do tasks with visibility of the object set as an A object, and B::doTask() to do tasks with visibility of the object set as an B object.
Now, let the call be like this:
B* ptr = new B();
A* ptrToB = ptr;
c.method(ptrToB); // pointer is passed
Within C::method(A *ptr), it may be something like:
void C::method(A * ptr) {
ptr->doTask(); this would actuall call A::doTask() or B::doTask() as dynamically binded
}
thanks to #texasbruce I found the answer, RTTI
The code will look like this:
A* someAOrBPtr = ...
...
B* testBPtr = dynamic_cast<B*>(someAOrBPtr);
if( testBPtr ){
// our suspicions are confirmed -- it really was a B
C->method(testBPtr);
}else{
// our suspicions were incorrect -- it is definitely not a B.
// The someAOrBPtr points to an instance of some other child class of the base A.
C->method(someAOrBPtr);
};
EDIT: In fact, I'll probably do the dynamic cast inside the C->method so there is only one
C::method(A* ptrOfBase)
and then do the appropriate thing (taking in or out the respective container-member-variable of C) inside the one 'method' of C.
Compiler is not smart enough to guess which method you wanna call. In the same situation of yours, you might actually want to call the the first version since you are using a A*. This leaves the programmer to work on: be specific. If you don't want to use ptr (which call the second version as you wished), you need to specifically cast it:
c.method(*((B*)ptrToB));
or better using dynamic cast:
c.method(*dynamic_cast<B*>(ptrToB));
This could be unsafe because you are "downcasting" in which case dynamic cast may throw exception and C style cast won't but will cause memory leak. You have to be very careful.

Is this a correct approach of using abstract classes with an OO approach?

Say we have 2 classes A and B. Both are subclasses of C, the superclass. Now let's assume that C defines a method areYouA(), that is a method that asks the object if it's an object of the A class.
So a possible code, in c++, would be:
C object1 = A()
C object2 = B()
if (object1.areYouA()==true){//crazy code here regarding if it's an A object}
if (object2.areYouA()==false){//crazy code here regarding if it's a B object}
From an OO POV is it correct to add a method to the B and C classes to ask their respective objects if they're of the A class??? If it's not correct, then what could be another approach to this???? My objective is obvious i have 2 classes A and B that i need, at some point i have portions of binary data that could be of the A class or the B class, also an object would initially be of the A class, as it gets full, it's structure needs to change and also some of it's behaviour, therefore becoming an object of the B class. So my approach to this was thinking of an abstract class as parent, and initially declaring a C object but storing an A object, and later storing a B object as it changes.
Is there another approch to this, like a pattern???
ADDITIONAL INFO:
I think i wasnt very clear about this. Let's say i want to store information from an A object in file1, and info from a B object in file2. If use its mother class as an interface, then how can i tell if it's an A object or a B object to store in the respective files?? Should i add an atribute to each object for their filename they belong too??? That means if i need to change the name of the file, then every object needs to change too.
The correct way is to use virtual functions to implement polymorphic behaviour:
struct C
{
virtual void do_crazy_stuff() { } // (see text below)
virtual ~C() { } // always have a virtual d'tor for polymorphic bases
};
struct A : C
{
virtual void do_crazy_stuff() { /* your crazy code for A */ }
};
struct B : C
{
virtual void do_crazy_stuff() { /* your crazy code for B */ }
};
Now you can use the same interface everywhere:
void process_data(C & x) // <-- Note: take argument by reference!!
{
x.do_crazy_stuff();
}
This works on any object of a type derived from C:
int main()
{
A x;
B y;
process_data(x); // calls x.A::do_crazy_stuff
process_data(y); // calls x.B::do_crazy_stuff
}
If you like, you can even declare the base function C::do_crazy_stuff as pure virtual; this makes the base class abstract (so it cannot be instantiated).
First off,
C object1 = A();
C object2 = B();
slices the objects. They are no longer of type A or B, they are C.
You can use pointer for this:
C* object1 = new A();
C* object2 = new B();
Although C pointers, they point to instances of A and B respectively.
Second, your approach is wrong. It seems like you're not taking advantage of polymorphism. If you have functionality that is shared between the classes, it should be implemented in C. If it changes, you should have virtual methods.
Knowledge about the type of an object is usually at least a code smell. You can alter the behavior simply by using polymorphism. Although if it really is necessary, the correct way would be using dynamic_cast:
C* object1 = new A();
A* pA = dynamic_cast<A*>(object1);
pA will be NULL if object1 doesn't point to an object of type A.
This is a design issue in my opinion you have to analyze your problem better. Why do you need to know the type of your object? Why you don't implement the interface method in your A and B classes, which will do whatever you need with a binary data? Take a look on visitor design pattern to get an image of how to implement it in this way.

scope of classes

class a
{
private:
b *b_obj;
public:
void set(int);
};
a::a()
{
b_obj = new b;
}
a::set(int s)
{
b_obj->c = s;
}
class b
{
public:
int c;
};
is this code valid?
if no, how do i make b_obj of a particular object (say a_obj) of class a ,modifiable in another class c...if a_obj i created in another class d....i am scared of a_obj going out of scope in class c.
hope you understand my question.
thanks a lot for taking the time to read my post
The code is nearly valid. class b needs to be declared (or at least forward declared) before it is referred to in class a, you do not specify the return type in the definition for a::set, and you have not provided a declaration for a'a default constructor. Here is the revised code, along with a test harness:
class b
{
public:
int c;
};
class a
{
private:
b *b_obj;
public:
a();
void set(int);
};
a::a()
{
b_obj = new b;
}
void a::set(int s)
{
b_obj->c = s;
}
int main()
{
a my_a;
my_a.set(42);
}
Now, just because the code is valid doesn't mean it's good:
You don't initialize c when default-constructing b.
You use raw pointers to dyanamically-allocated b's. Use automatic variables instead, whenever possible. Among the the reasons for this are ...
You never delete the b you new'ed in a'a constructor. This results in a memory leak. If you had avoided the use of dynamic allocation in the first place, this would not be an issue.
Well,
*b_obj = *other_b_obj;// equality of objects values
b_obj = other_b_obj; // equality for pointer values
assuming that b_obj is an object and other_b_obj is a pointer:
b_obj = *other_b_obj;
Assuming the reverse:
b_obj = &other_b_obj;
Assuming both are pointers:
b_obj = other_b_obj;
for your final question, new is not compulsory for assgining pointers. A pointer may point to an exiting object. However, if you want the pointer to point to a new object, use then new keyword, which attempts to create new object and returns the new object address.
is this code valid?
The code is almost valid, except that you forgot to state the return type of the set function:
void a::set(int s)
However, the set function will really change the c member of b_obj. It is public, so the compiler will allow it.
BTW, why don't you try for yourself?
As an aside, while you're studying, look at constructors, destructors, assignment operator and implement them to free the object b_obj properly. You can even use a shared_ptr for that.
Also, I wouldn't advise you to use such a dull name as lowercase a for a class.

polymorphism with =operator using pointer base class

So here is the deal, I think I need to go another route regarding the pattern I am using but I thought I would get some expert opinions first.
I have a class (UsingClass) that maintains a dynamic list of Base class pointers. When adding a new object to the list I have to figure out what type of object it is because I can't really make it work in a polymorphic manner. The line below tagged "THIS WILL NOT WORK LIKE I WANT IT TO!!" would ideally polymorphically use the =operator from the Derived class of interest, but unfortunately it only uses the default =operator for the Base class.... probably would work if I made Base pure virtual (basically confine it use to an interface with no data members of its own), but I don't really want to have the Derived classes hold members that are common between both (maybe I need to just cut bait and do it).
I think I may just completely be using the wrong pattern but I don't know what alternatives I should consider.
I know the code does not necessarily compile but please work with me. Thanks in advance!
//code block
class Base {
protected:
int x;
float y;
string type; // default to Derived1 or Dervied2 depending on the object inst
public:
virtual int functionM(int l) = 0;
int functionN(int P);
};
class Derived1 : public Base {
protected:
int a;
public:
int functionM(int l);
float functionR(int h);
};
class Derived2 : public Base {
protected:
int b;
float r;
public:
int functionM(int l);
float functionR(int h);
};
#define MAX_ARRAYSIZE 10
class UsingClass {
private:
Base* myDerived1And2DynamicList[MAX_ARRAYSIZE];
int indexForDynamicList;
public:
void functionAddDerivedToList(*Base myInputPtr) {
if((indexForDyanmicList + 1) < MAX_ARRAYSIZE) {
if(myInputPtr->type == "Derived1") {
myDerived1And2DynamicList[indexForDyanmicList+1] = new Derived1;
*myDerived1And2DynamicList[indexForDyanmicList+1] = *myInputPtr; // THIS WILL NOT WORK LIKE I WANT IT TO!!
} else if (myInputPtr->type == "Derived2") {
myDerived1And2DynamicList[indexForDyanmicList+1] = new Derived2;
*myDerived1And2DynamicList[indexForDyanmicList+1] = *myInputPtr; // THIS WILL NOT WORK LIKE I WANT IT TO!!
}
}
} // end of void function
};
Rather than checking the type you could simply add a virtual function to the class 'Base' and call that. This would simplify void functionAddDerivedToList(*Base myInputPtr) to the following:
void functionAddDerivedToList(*Base myInputPtr)
{
if((indexForDyanmicList + 1) < MAX_ARRAYSIZE) {
myDerived1And2DynamicList[indexForDyanmicList+1] = myInputPtr->clone();
}
}
Clone would always be implemented to call the class's copy constructor. So in Base, add the following:
virtual Base* clone() = 0;
The implementation would always take this form (example is for Derived1, a subclass of Base in your example):
virtual Base* clone() { return new Derived1(*this); }
One problem I see is that you are sing C-style array to contain a list of "Base" objects. Note that the size of the elements in the array in this case will be the sizof(Base), which is different with sizeof(Derived1) and sizeof(Derived2). Both derives may be different as well. What you can do in this case is to have the array contain pointers of Base objects instead of the actual objects. That will make the size uniformed to 4 bytes and you can access the objects in your array as pointers. Because the array now contain pointers you do not have to determine the type if you simply want to insert them in the array.
void functionAddDerivedToList(Base* myInputPtr)
{
if((indexForDyanmicList + 1) < MAX_ARRAYSIZE)
myDerived1And2DynamicList[indexForDyanmicList+1] = myInputPtr;
}
If you want to access the object from the array you can do something like this.
Base* p = myDerived1And2DynamicList[index];
p->MyMethod();
You can trust that the correct MyMethod function will be called based on the actual type of p in this case.
I have a class (UsingClass) that maintains a dynamic list of Base class pointers.
Sorry, but you have not (wrong syntax). But don't go that way.
First, give your Base class a virtual destructor. Otherwise you will experience memory leaks.
Then, redesign your UsingClass container. Give it a vector of shared_pointer to Base member to hold dynamically alocated polymorphic objects. (If you use a non C++0x-compiler, you can use std::tr1::shared_ptr.)
class UsingClass {
private:
std::vector<std::shared_ptr<Base> myList;
// int indexForDynamicList; is now myList.size()
public:
void Add(Base* myInputPtr) {
myList.push_back(myInputptr);
}
// ...
};
To add polymorphic objects, use
UsingClass container;
container.add(new Base);
container.add(new Derived1);
container.add(new Derived2);
You can call all polymorphic methods by iterating
for (size_t i = 0; i < myList.size(); ++i)
{
myList->functionM(); // give the function a more "speaking" name
}
By using shared_ptr you can hold many pointers to one object and don't have to care about freeing memory. Copying the pointers will not copy objects (so called shallow copy). If you really need to copy objects also (so called deep copy), your Base and derived classes will have to implement a virtual clone() method.