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;
};
Related
I am very new to c++ so I am trying to get a feeling of how to do things the right way in c++. I am having a class that uses one of two members. which one gets determined at instantiation. It looks something like
main() {
shared_pointer<A> a = make_shared<A>();
if ( checkSomething ) {
a->setB(make_shared<B>());
} else {
a->setC(make_shared<C>());
}
a->doStuff();
class A {
public:
doStuff() {
/*here I want to do something like call
m_b->doStuff() if this pointer is set and m_c->doStuff() if
that pointer is set.*/
}
setB( B* p ) { m_b = p; }
setC( C* p ) { m_c = p; }
B* m_b;
C* m_c;
}
}
B and C are some classes with doStuff() member function
There are many members like doStuff. Ideally I would avoid checking for nullptr in each of them. What is the best/most efficient/fastest way to create a switch between those two members?
Is there a way to use a static pointer so that I have a member
static **int m_switch;
and do something like
m_switch = condition ? &m_b : &m_c;
and call
*m_switch->doStuff();
Does the compiler here also replace the extra pointer hop because it is a static?
Is there any other smart way to do those switches?
Normally, class A would be an interface class, which both B and C would inherit and implement. But it sounds like you cannot do this for whatever reason.
Since you want to emulate this, you can start by making the interface:
class A_interface
{
public:
virtual void doStuff() = 0;
virtual void doThings() = 0;
virtual void doBeDoBeDo() = 0;
};
And then you make a template wrapper:
template< class T >
class A : public A_interface
{
public:
void doStuff() override { target.doStuff(); }
void doThings() override { target.doThings(); }
void doBeDoBeDo() override { target.doBeDoBeDo(); }
private:
T target;
};
This essentially does half of what your own example class A was trying to do, but now you can use a common interface. All you need to do is construct the correct templated version you want:
std::shared_ptr<A_interface> a;
if( checkSomething ) {
a = std::make_shared<A<B>>();
} else {
a = std::make_shared<A<C>>();
}
a->doStuff();
You need to have both members implement a common interface to use them similarly. But in order to do that, you need to define the interface and relay the calls to the B and C classes.
// existing classes
class B
{
public:
void doStuff() { std::cout << "B"; }
};
class C
{
public:
void doStuff() { std::cout << "C"; }
};
// define your interface
class I
{
public:
virtual void doStuff() = 0;
};
// new classes
class D : public B, public I
{
public:
void doStuff() override { B::doStuff(); }
};
class E : public C, public I
{
public:
void doStuff() override { C::doStuff(); }
};
// your A class
class A
{
public:
D* b = nullptr; // now type D
E* c = nullptr; // now type E
// your toggle
I* getActive()
{
if (b)
return b;
else
return c;
}
// simple doStuff() function
void doStuff()
{
getActive()->doStuff();
}
};
int main()
{
A a;
if (true)
a.b = new D; // need to initialize as D
else
a.c = new E; // need to initialize as E
a.doStuff(); // prints B
}
But typing this up made me realize that defining D and E could get really tiresome and against what you're trying to save. However, you can define a template to create them like #paddy has done.
There's no one-size-fits-all solution for your problem. What to use depends on your particular problem. A few possible answers:
Interfaces
Strategy Pattern
Pointers (to hold a function or class which implements doStuff)
An interface is like a contract. Any class which inherits from the interface must implement its members. For instance,
class IDoesStuff
{
public:
virtual ~IDoesStuff() {};
virtual void DoStuff() = 0;
};
Can now be used by other classes:
class Foo : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
class Bar : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
And now, in general, one may do:
Foo foo;
IDoesStuff *stuffDoer= &foo;
stuffDoer->doStuff();
This can be used in your particular use case as follows:
class A
{
IDoesStuff *stuffDoer; // Initialize this at some point.
public:
void doStuff() { stuffDoer->doStuff(); }
};
First you must change your memebr variables m_b and m_c to std::shared_ptr.
Add a member variable of type std::function(void()) to hold the target function you want to call. In your sample it is do_stuf.
In your setter functions you can bind target function to your std::function and in do_stuf just call std::function.
(You need a C++11 compiler)
class B
{
public:
void doStuff()
{
}
};
class C
{
public:
void doStuff()
{
}
};
class A
{
public:
void doStuff()
{
m_target_function();
}
void setB(std::shared_ptr<B> p)
{
m_b = p;
m_target_function = std::bind(&B::doStuff, m_b.get());
}
void setC(std::shared_ptr<C> p)
{
m_c = p;
m_target_function = std::bind(&C::doStuff, m_c.get());
}
std::shared_ptr<B> m_b;
std::shared_ptr<C> m_c;
std::function<void()> m_target_function;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::shared_ptr<A> a = std::make_shared<A>();
bool use_B = false;
if (use_B)
{
a->setB(std::make_shared<B>());
}
else
{
a->setC(std::make_shared<C>());
}
a->doStuff();
}
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
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.
I want to call a method from A class in constructor of other class
I googled, but did not find any answer
For example, I have :
class A{
void doWork();
}
class B{
B(){
//here i want to have doWork method
}
}
You told us not enough to choose proper solution. Everything depends on what you are trying to achieve. A few solutions:
a) Mark A method as static.
class A
{
public:
static void DoSth()
{
// Cannot access non-static A members here!
}
};
class B
{
public:
B()
{
A::DoSth();
}
};
b) You can instantiate A in place
class A
{
public:
void DoSth()
{
// Do something
}
};
class B
{
public:
B()
{
A a;
a.DoSth();
}
};
c) You can put A's instance into B:
// A remains as in b)
class B
{
private:
A a;
// or: A * a;
public:
B()
{
a.DoSth();
// or: a = new A; a->DoSth();
// Remember to free a somewhere
// (probably in destructor)
}
}
d) You may derive B from A:
class A
{
protected:
void DoSth()
{
}
};
class B : public A
{
public:
B()
{
DoSth();
}
};
e) You can forget about A class and make DoSth a function:
void DoSth()
{
// ...
}
class B
{
public:
B()
{
DoSth();
}
}
Since you provided not enough data, you have to choose solution on your own.
In order for that to work you'd need to subclass it.
So it'd be like this:
class A {
doWork();
}
class B : A {
B(){
doWork();
}
}
You could also do it like so going for a HAS-A rather than IS-A relationship:
class A {
doWork();
}
class B {
A myA;
B(){
myA.doWork();
}
}
Without knowing more of what you are doing I'd go with the top (IS-A) solution which is what I think you are trying to do.
Or
class A
{
public:
static void doWork();
};
class B
{
B(void)
{
A::doWork();
}
};
?
PS: Here B::B() will be private
Say I have a class called Person, who owns three kinds of pets:
class Person
{
public:
accept(Pet a);
private:
Dog d; // is a Pet
Cat c; // is a Pet
Fish f; // is a Pet
}
Person::accept(Pet a)
{
// if pet is Dog, then
d = a;
// if pet is Cat, then
c = a;
// if pet is Fish, then
f = a;
};
I guess typeid can be used here. However, it still looks weird to me.
Is there some kind of polymorphism, virtual function or some OOP pattern that can be applied?
-- EDIT --
Sorry for the bad example here. Let me try another one:
// Usually a context contains three different resources:
class Context
{
public:
setResource(Resource *r);
private:
Buffer *b_; // is a Resource
Kernel *k_; // is a Resource
Sampler *s_; // is a Resource
};
Context::setResource(Resource *r) { // same logic as Person::accept() above }
Context::handlingBuffer() { if (b_) b_->init(); ... }
Context::run() {
if (b_ && k_) {
k_.setBuffer(b_);
k_.run();
}
}
...
In this case, looks like adding a Resource *r_[3] in Context will make things more complicated.
So, is it possible to pass a pointer of base class of Resource to setResource(), and it can automatically decide which resource to set?
Since you are holding Pets by value, you can forget polymorphism and just overload the accept member function:
class Person
{
public:
accept(const Dog& a) { d_ = a; }
accept(const Cat& a) { c_ = a; }
accept(const Fish& a) { f_ = a; }
private:
Dog d_; // is a Pet
Cat c_; // is a Pet
Fish f_; // is a Pet
};
A common method to letting code depend on the runtime type is double dispatch, a.k.a. the Visitor pattern:
class ResourceContext
{
public:
virtual void setResource(Buffer* r) = 0;
virtual void setResource(Kernel* r) = 0;
virtual void setResource(Sampler* r) = 0;
};
class Resource
{
public:
virtual void AddToContext(ResourceContext* cxt) = 0;
[... rest of Resource ...]
};
class Buffer : public Resource
{
public:
void AddToContext(ResourceContext* cxt) { cxt->SetResource(this); }
};
// Likewise for Kernel and Sampler.
class Context : public ResourceContext
{
public:
void setResource(Resource* r) { r->AddToContext(this); }
void setResource(Buffer *r) { b_ = r; }
void setResource(Kernel *r) { k_ = r; }
void setResource(Sampler *r) { s_ = r; }
private:
Buffer *b_; // is a Resource
Kernel *k_; // is a Resource
Sampler *s_; // is a Resource
};
For me the approach itself looks wrong. As #LihO said in his comment, polymorphism helps to treat different type objects in the same manner. So from polymorphism point of view, your design should look as:
// Usually a context contains three different resources:
class Context
{
public:
setResource(Resource *r);
private:
std::vector<Resource*> resources_;
};
The rest should be resolved by virtual functions of Resource class.
Using dynamic_cast often means your design is not perfect.
For your simple example code, I agree with juanchopanza. However, if you want to keep the structure of your class Person with pointers, you could use dynamic_cast<>, e.g.
struct Pet { /* ... */ };
struct Dog : public Pet { /* ... */ };
struct Cat : public Pet { /* ... */ };
struct Fish : public Pet { /* ... */ };
struct Spider : public Pet { /* ... */ };
class Person {
Dog*dog;
Cat*cat;
Fish*fish;
Spider*yuck;
template<typename PetType>
static bool accept_pet(Pet*pet, PetType*&my_pet)
{
PetType*p = dynamic_cast<PetType*>(pet);
if(p) {
my_pet = p;
return true;
}
return false;
}
public:
Person()
: dog(0), cat(0), fish(0), yuck(0) {}
void accept(Pet*pet)
{
if(accept_pet(pet,dog)) return;
if(accept_pet(pet,cat)) return;
if(accept_pet(pet,fish)) return;
if(accept_pet(pet,yuck)) return;
throw unknown_pet();
}
};
I should add, that dynamic_cast<> should be avoided if it can. Often (but not always) a design that makes a dynamic_cast<> necessary can be improved to avoid that. This also applies here, when simply overloading the accept() (as in juanchopanza's answer) is an alternative.
Inspired by #molbdnilo, I found a simpler way to achieve my goal:
class Resource
{
public:
virtual void AddToContext(Context* c) = 0;
};
class Buffer : public Resource
{
public:
void AddToContext(Context* c) { c->SetResource(this); }
};
// Likewise for Kernel and Sampler
class Context
{
public:
void SetResource(Resource *r) { r->AddToContext(this); }
void SetResource(Buffer *b) { b_ = b; }
void SetResource(Kernel *k) { k_ = k; }
void SetResource(Sampler *s) { s_ = s; }
...
private:
Buffer *b_;
Kernel *k_;
Sampler *s_;
};
It is not quite like Visitor pattern at this point, but it is relatively concise and works great.