Accessing Properties/Functions of Subclasses C++ - c++

I am having a design problem in my program because I need to occasionally access properties & methods of subclasses that are all stored in a vector of base class pointers. My code looks something like this:
class B1;
class B2;
class Base {
private:
int id, a, b;
public:
virtual int getA() { return a; }
virtual int getB() { return b; }
virtual B1 *getB1() { return NULL; } //seems like a bad idea
virtual B2 *getB2() { return NULL; } //to have these two functions
Base(int newId) { id = newId; }
};
class B1 : public Base {
private:
int x;
public:
int getX() { return x; }
B1 *getB1() { return this; }
};
class B2 : public Base {
private:
int y;
public:
int getY() { return y; }
B2 *getB2() { return this; }
};
class Thing {
private:
std::vector<Base*> bases;
void addBase(Base *base) { bases.push_back(base); }
void doB1Stuff();
void doB2Stuff();
void setAandB(int ID, int newA, int newB); //set a and b of one of the elements in bases vector based upon the id given
};
The problem is if I need to access x or y in Thing, like this below:
void Thing::doB1Stuff() {
for(std::vector<Base*>::iterator it = bases.begin(); it != bases.end(); ++it) {
if (it->getB1()) {
//do stuff with b1
}
}
}
The code above should work, but if it seems a bad idea because one could easily forget to check if the pointer is null before using B1/B2 properties like this:
void Thing::doB2Stuff() {
for(std::vector<Base*>::iterator it = bases.begin(); it != bases.end(); ++it) {
std::cout << it->getY(); //I believe this will crash the program if a NULL pointer is returned
}
}
My question thus is: what is a good way of accessing subclass properties? I was thinking of having two separate vectors for B1s and B2s in Thing, but that doesn't seem like a good idea either because I need to be able to set a and b easily. Any thoughts?

What you have is perfectly fine: as long as you do not store NULLs in the bases vector of pointers, there is no need to null-check the values returned from the iterator. Unfortunately, a vector of pointers is your only option for containers of polymorphic objects. You can make a vector of shared pointers to simplify dealing with deletions, but the basic idea would remain the same.

You can check whether the item you are accessing is the right subclass type you are looking for although to do this you need run time type information (rtti) included.
Then if it is of a certain type and not null you can cast it to that type and call the correct function.
Also you can use dynamic_cast although for this to work you need rtti again and it is essentially the same as checking yourself and then static casting.

You're right that's not a great way of approaching the problem, you can use dynamic_cast to have a safe way to determine which object to use, but that is bad code smell to me.
What I would do instead to access sub properties is create a virtual function that returns the value you want in the Base class.
Example:
class Base {
private:
int id, a, b;
public:
virtual int getA() { return a; }
virtual int getB() { return b; }
virtual int getSubValue() = 0; //
Base(int newId) { id = newId; }
};
class B1 : public Base {
private:
int x;
public:
int getSubValue() { return x; }
};
class B2 : public Base {
private:
int y;
public:
int getSubValue() { return y; }
};
Then you can just call it->getSubValue() to get the sub value you request.
This is my opinion and there are many ways to handle this, but this is what I would suggest based on the information you've given.

Related

How to add derived class objects to an array of base class type?

unfortunately, I can't use std::vector and have to use plain C++ arrays. I got the following code:
class Base
{
}
class DerivedCar : Base
{
public:
DerivedCar(int a) a(a) {};
private:
int a;
}
class DerivedHouse : Base
{
public:
DerivedHouse(float b) b(b) {};
private:
float b;
}
class Vector
{
Vector() :
index(0)
void add(const DerivedCar& car)
{
vec[index] = new DerivedCar(car.a);
index++;
}
void add(const DerivedHouse& house)
{
vec[index] = new DerivedHouse(house.b);
index++;
}
private:
Vector vec[100];
int index;
}
int main()
{
Vector vector;
DerivedCar car(100);
DerivedHouse house(2.f);
vector.add(car);
vector.add(house);
}
I would like to have an array of type Base and add objects of a derived type.
Is there a better approach to this other than the way I did? What would be the best way to keep copying of objects at a minimum.
How to add derived class objects to an array of base class type?
You can not put derived class objects into raw array or std::vector of base class because the derived class objects are usually larger and so simply do not fit there.
Is there a better approach to this other than the way I did?
Better approaches are certainly out there. One good example of such containers with polymorphic elements is boost::base_collection. Read its documentation and its source code. If you do not understand some detail in it then ask about that detail in Stack Overflow.
What would be the best way to keep copying of objects at a minimum.
Containers that only contain pointers to objects and intrusive containers
keep copying of objects at minimum. However such containers do not
manage the objects and so responsibility of objects life time has
to be taken by something outside.
Here is a possible way that implements a linked list:
class Base
{
};
class DerivedCar : public Base
{
public:
DerivedCar(int a) { _a = a; };
private:
int _a;
};
class DerivedHouse : public Base
{
public:
DerivedHouse(float b) { _b = b; };
private:
float _b;
};
class Object
{
public:
const Base *data;
const Object *next;
};
class Vector
{
public:
void add(const Base& v)
{
Object item;
item.data = &v;
head.next = &item;
index++;
}
private:
Object head;
int index = 0;
};
int main()
{
Vector vector;
DerivedCar car(100);
DerivedHouse house(2.f);
vector.add(car);
vector.add(house);
}

I have different classes and I want to make a vector with objects from those classes and sort it by a value

I have the first class.
class Class1
{
public:
Class1();
double getVal();
bool operator<(Class1& A) { return getVal() > A.getVal(); }
virtual ~Class1();
}
And from this class I derive two classes.
class Class2 : virtual public Class1
{
protected:
int val1;
public:
int getVal(){ return val; }
bool operator<(Class1& A) { return getVal() > A.getVal(); }
}
And the second class.
class Class3 : virtual public Class1
{
protected:
double val2;
public:
double getVal(){ return val; }
bool operator<(Class1& A) { return getVal() > A.getVal(); }
}
And finally from these classes I derive one class.
class Class4 : public Class2, public Class3
{
protected:
char* info;
public:
double getVal(){ return val1+val2; }
bool operator<(Class1& A) { return getVal() > A.getVal(); }
}
And in main I have:
void main(){
vector<Class1*> vec;
vec.push_back(new Class2(3));
vec.push_back(new Class3(5));
vec.push_back(new Class4(2));
sort(vec.begin(),vec.end());
}
The code is pushing back objects in the vector just fine, but when I'm trying to sort it nothing happens.
I suspect that is something wrong with the parent class (Class1) and mainly the getVal() method, but I don't know what to do.
The question is: How can I sort this vector?
The problem here is that you have a vector of pointers. Therefore the comparison done by std::sort is done using the pointers and not the structures pointed to by them.
For it to work, you have to either provide a global operator< function which takes two pointers as arguments. Or you provide a comparison function as a third argument to std::sort. Both needs to dereference the pointers.
Also, you still need to mark your functions as virtual for polymorphism to work.

Generic way to set particular parameters of a polymorphic member variable

Sorry for the convoluted title of my question, conceptually it is quite simple but I can't find any good design to do it.
I have a base class accessible by the end user :
class A {
private:
// m is a functor
Base* m;
};
class Base {
public:
virtual void someInterface();
};
class DerivedT1 : public Base {
public:
virtual void someInterface()
{
some_parameter++;
}
private:
int some_parameter; // how to set?
};
class DerivedT2 : public Base {
public:
virtual void someInterface()
{
some_other_parameter += a_third_parameter;
}
private:
double some_other_parameter; // how to set?
double a_third_parameter; // how to set?
};
And I am trying to find the most generic way to set some_parameter and some_other_parameter from A's public interface.
I have thought of giving a number to my parameters but this sounds really ugly.
Is there any beautiful, object-oriented way to do this ?
you want to use A's public interface to set derived class parameters:
you can define a public function In A, which have a Base* parameter:
class A
{
public:
void setter(const Base *p);
{
m = p;
}
};
if you want to set Drived1 you can define a object of Derived1, can pass it to setter;
I think you want to pass value using A's public function, you must know the type of pointer of Base*,so you can pass value by the constructor of Derived1 or Derived2!
I nothing else works, you could always use a dynamic cast:
DerivedT1 *d1 = dynamic_cast<DerivedT1>(m);
if (d1 != nullptr)
{
// do something with derived 1
}
else
{
DerivedT2 *d2 = dynamic_cast<DerivedT2>(m);
if (d2 != nullptr)
{
// do something with derived 2
}
}
But if you need that, it's usually a sign that there is something wrong with your design.
If you want to do something along these lines
A a; a.setAlgorithmFamily(Algorithm::Type1);
a.getAlgorithmImplementation().setSomeParameter(34);
This is a quick and kind of dirty example of how you could do it. A::setAlgorithmType is basically a factory pattern in it's simplest form.
nclude <iostream>
using namespace std;
class Algorithm {
public:
virtual void setParameter(int value) = 0;
};
class AlgoX : public Algorithm {
int mX;
public:
void setParameter(int value) {
cout <<"Setting X to " <<value <<endl;
mX = value;
}
};
class AlgoY : public Algorithm {
int mY;
public:
void setParameter(int value) {
cout <<"Setting Y to " <<value <<endl;
mY = value;
}
};
class A {
public:
void setAlgorithmType(std::string type) {
cout <<"Now using algorithm " <<type <<endl;
if(type == "X")
mAlgorithm = new AlgoX();
else if(type == "Y")
mAlgorithm = new AlgoY();
}
Algorithm* getAlgorithmImplementation() { return mAlgorithm; }
private:
Algorithm* mAlgorithm;
};
int main(int argc, char** argv) {
A a;
a.setAlgorithmType("X");
a.getAlgorithmImplementation()->setParameter(5);
return 0;
}
This gives:
Now using algorithm X
Setting X to 5

class design woes

I'd like to get some advice on designing classes in a situation similar to the example below. B and C objects may or may not have a number component. The problem is that there is no way to selectively call a NumberComponent constructor. Is there a better way to design this?
class NumberComponent
{
public:
//Objects which don't have a number component just store a null pointer.
//Any time we do anything here, we have to make sure p_int isn't null.
NumberComponent() : p_int(0) { }
NumberComponent(int x) { p_int = new int(x); }
~NumberComponent() { delete p_int; }
void DoSomething() { if(p_int) ++(*p_int); }
//In real situation, this will be another complex class object.
//Using an int* here to keep this class simple for example.
int* p_int;
};
//B objects may or may not have a number component.
class B : public NumberComponent
{
public:
//If hasNumberComponent is false, we'd like to call the default constructor.
//If hasNumberComponent is true, we'd like to call NumberComponent(int) constructor.
B(int x, bool hasNumberComponent) {}
int value;
};
//C objects may or may not have a number component.
class C : public NumberComponent
{
public:
//If hasNumberComponent is false, we'd like to call the default constructor.
//If hasNumberComponent is true, we'd like to call NumberComponent(int) constructor.
C(int x, bool hasNumberComponent) {}
int value;
};
int main()
{
//myList contains NumberComponent* to B and C objects
std::list<NumberComponent*> myList;
myList.push_back(new B(5, true));
myList.push_back(new C(3, true));
for(std::list<NumberComponent*>::iterator i = myList.begin(); i != myList.end(); ++i)
(*i)->DoSomething();
//These objects don't have a Number component.
B b(2, false);
C c(1, false);
return 0;
}
Although there are better designs, you can solve your immediate problem like this:
class NumberComponent
{
public:
NumberComponent(int x,bool hasNumberComponent)
: p_int(hasNumberComponent ? new int(x) : 0) { }
~NumberComponent() { delete p_int; }
void DoSomething() { if(p_int) ++(*p_int); }
//In real situation, this will be another complex class object.
//Using an int* here to keep this class simple for example.
int* p_int;
};
//B objects may or may not have a number component.
class B : public NumberComponent
{
public:
B(int x, bool hasNumberComponent) : NumberComponent(x,hasNumberComponent) {}
int value;
};
//C objects may or may not have a number component.
class C : public NumberComponent
{
public:
C(int x, bool hasNumberComponent) : NumberComponent(x,hasNumberComponent) {}
int value;
};
There's a lot of bad design here. Have you considered to use inheritance for what it was invented for:
class B
{
public:
B(int x):
m_val(x)
{
}
virtual void doSomething()
{
//something
}
private: //might be protected as well
m_val;
};
class BWithNumberComponent : public B
{
public:
BWithNumberComponent(int x):
B(x),
m_numberComponent(x)
{
}
virtual void doSomething()
{
//something else
}
private:
NumberComponent m_numberComponent;
};

Class member function pointers in C++

I want to call a member function of another class on an object, but I cant seem to figure out how this works. As example code on how it should work:
Class A {
void somefunction(int x);
}
Class B : A {
void someotherfunction(int x);
}
Class C {
void x() {
callY(&ofthefunction);
} //here you call the function, you dont have an object yet, and you don't know the argument yet, this will be found in function callY
void Y(*thefunction) {
find int x;
if(something)
A a = find a;
a->thefunction(x);
else
B b = find b;
b->thefunction(x);
}
}
I hope this makes sence, It is also possible to split this in 2 methods, Y1 and Y2, but seeing as 90% of the code is the same (finding things in a XML file), only the object and argument where to save it is different, i'd like to do this
You can use something known as a virtual function. By the way, your syntax is hideous, it's class not Class, you need braces for your conditionals, and a judicious application of public, some extra semicolons, etc. It would be appreciated if you would go near a compiler before coming here, y'know.
class A {
public:
virtual void somefunction(int x);
};
class B : public A {
public:
virtual void somefunction(int x);
};
void func(A& a) {
int x = 0;
// Do something to find x
a.somefunction(x);
// calls A::somefunction if this refers to an A
// or B::somefunction if it's a B
}
int main() {
A a;
func(a); // calls A::somefunction
B b;
func(b); // calls B::somefunction
}
What you want to do can be done, although I woudn't solve it this way:
class A {
public:
virtual int doit(int x) { return x+1; }
};
class B : public A {
public:
int doit2(int x) { return x*3; }
int doit(int x) { return x*2; }
};
int foo(int (A::*func)(int), int x, bool usea) {
if (usea) {
A a;
return (a.*func)(x);
} else {
B b;
return (b.*func)(x);
}
}
int main() {
int (A::*bla)(int) = &A::doit;
foo(bla, 3, true);
foo(bla, 3, false);
}
However, for this to work, the following has to be satisfied:
You must use function pointers of the base class (e.g. int (A::*bla)(int)), otherwise you won't be able to call it on that base class (e.g. int (B::*bla)(int) can only be used on B instances, not on A instances, even if the method is already defined in A).
The methods must have the same names as in the base class
To use overriding (e.g. different impl in derived class), you have to use virtual functions.
But I would rather rethink your design...
No, that won't work at all. A pointer to a member of A will always point to that function, even when it's called on B because B inherits from A.
You need to use virtual functions. I see DeadMG has beaten me to it.