So I decided to use the Factory Design Pattern along with Dependency Injection.
class ClassA
{
Object *a, *b, *c;
public:
ClassA(Object *a, Object *b, Object *c) :
a(a), b(b), c(c) {}
};
class ClassB : public ClassA
{
Object *d, *e, *f;
public:
ClassB(Object *a, Object *b, Object *c, Object *d, Object *e, Object *f) :
ClassA(a, b, c), d(d), e(e), f(f) {}
};
Now, the problem is that classB has too many arguments for the constructor. This is a single inheritance-layer example, but when the inheritance layers start getting deeper, and when each layer-class needs more objects to be constructed, the constructor in the top layer ends requiring too many arguments in order to be made!
I know I could use setters instead of the constructor, but is there any other way?
Setter are not recommended for such things because they result in a partially constructed object which is very error prone. A common pattern for constructing an object that requires many parameters is the use of builder. The responsibility of ClassBBuilder is to create ClassB objects. You make ClassB constructor private and allow only builder to call it using friend relationship. Now, the builder can look somehow like this
ClassBBuilder {
public:
ClassBBuilder& setPhoneNumber(const string&);
ClassBBuilder& setName(consg string&);
ClassBBuilder& setSurname(const string&);
ClassB* build();
}
And you use the builder likes this:
ClassB* b = ClassBBuilder().setName('alice').setSurname('Smith').build();
build() method checks that all required parameters were set and it either returns properly constructed object or NULL. It is impossible to create partially constructed object. You still have a constructor with many arguments, but it is private and called only in a single place. Clients won't see it. Builder methods also nicely document what each parameter means (when you see ClassB('foo', 'bar') you need to check the constructor to figure out which parameter is a name and which is a surname).
This is one of the C++ problems (if this can be called a problem). It does not have solution other than trying to keep the number of parameters of the ctor minimal.
One of the approaches is using the props struct like:
struct PropsA
{
Object *a, *b, *c;
};
class ClassA
{
ClassA(PropsA &props, ... other params);
};
This seems obvious but I did used this several times. In many cases it turns out that some group of params are related. In this case it makes sense to define a struct for them.
My worst nightmare of this sort was with the thin wrapper classes. Methods and data fields of the base can be accessed directly while all ctors has to be duplicated. When there are 10+ ctors, creating a wrapper starts to be a problem.
I think what you're describing is not a problem in C++ - in fact, C++ reflects the dependencies expressed by your design fairly well:
To construct an object of type ClassA, you need to have three Object instances (a, b and c).
To construct an object of type ClassB, you also need to have three Object instances (d, e and f).
Every object of type ClassB can be treated like an object of type ClassA.
This means that for constructing an object of type ClassB you need to provide three Object objects which are needed for the implementation of the ClassA interface, and then another three for the implementation of the ClassB interface.
I believe the actual issue here is your design. You could consider different approaches to resolve this:
Don't let ClassB inherit ClassA. May or may not be an option depending on whether you need homogenous access to objects of either type (say, because you have a collection of ClassA* and this collection could also contain pointers to ClassB).
Look for objects which always appear together. Like - maybe the first two objects passed to either constructor (a and b or d and e) represent some sort of pair. Maybe an object identifier or the like? In this case, it may be beneficial to introduce a dedicated abstract (read: type) for this.
Related
I'm new to C++, with a C# background. I'm trying to use dependency injection commonly used in C# in C++ and I'm confused about the different ways to declare dependencies and pass them in and why I would use one over the other. Let's assume A depends on B.
Approach #1 - declare as object and take object
class A
{
private:
B _b;
public:
A(B b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
Approach #2 - declare as object and take reference
class A
{
private:
B _b;
public:
A(B &b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
Approach #3 - declare as reference and take object - scratch this - undefined behavior
class A
{
private:
B &_b;
public:
A(B b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
Approach #4 - declare as reference and take reference
class A
{
private:
B &_b;
public:
A(B &b): _b(b) { }
void Foo()
{
_b.Bar();
}
}
I've tried all of the above and they all seem to work. Is there any difference between them? and if so why should I choose one over the other? my preference is #1 because I find it the most familiar and intuitive.
I've found a similar discussion discussion here but that's more about Pointers vs References.
One of the main difference between C# and C++ in this regard is that in C# classes are reference types whereas in C++ they are value types.
Approach 1 and 2 are based on copy construction. This could work if the object passed to the constructor is exactly a B. But it might fails due to object slicing if you'd use a derived class of B. Approach 2 might also fail if the source object is a constant.
Approach 3: no longer considered (scratched in your question)
Approach 4: is ok, provided the object passed by reference continues to exist as long as the object. However if function B::Bar() is not a virtual function, B::Bar() would always be called in Foo(), even if you'd use a class derived from B with its own implementation of Bar().
Approach 5: use a smart pointer and clone the object passed by reference (either with a clone() member, or by using templated constructor):
class A
{
private:
unique_ptr<B> _b;
public:
template<class T>A(const T&b): _b(make_unique<T>(b)) { }
void Foo()
{
_b->Bar();
}
};
Online demo
In your case I'd say that best solution from all mentioned is taking and storing reference. The whole point of dependency injection is using pure virtual interface without even knowing how something is implemented. It means that underneath you want vtable lookup that will execute whatever implementation is for object that is referenced. This way you can expect reference for Animal where callers will provide Elephant or Cat implementation of Animal. Moreover, if you use pure virtual interface (with at least one pure virtual function inside) you can't even pass object by value because you can't create object of pure virtual type.
As far as I remmember, C# similarly to Java distinguishes objects from builtin types and objects are passed by reference by default. In C/C++ you explicitly pass everything the way you want, so in your cases you have:
Copy of temporary copy of B You make more copies than you need. If your object is big, it will cause performance loss.
Copy of B If you simply want to store copy of some object it seems to be better way but you created not needed limitation here. If you make copy of an object, you won't modify original object. By passing it by non-const reference you create this limitation and you can't take const objects because of that. If you simply want to take some object by reference and store copy of it, most of the time you want const reference. Exceptions might be in case of noncopyable objects.
reference to temporary copy of B (invalid)
Reference to B Is completely different story. Here you don't store copy of an object but point to original one, so every change you make on this object will be visible to anyone else that has access to object you received. That's more or less how objects work by default in languages like Java. Moreover, you can use virtualization as I mentioned before. The only drawback is that you have to ensure that this object exists as long as you are using it - you are not the owner of B. You just use that but someone has control of it's existence.
As you can see, in first case Second case creates some not needed limitation. You create copy of non-const
I have two classes
class A {
public:
virtual void doStuff() = 0;
};
class B : public A {
int x;
public:
virtual void doStuff() override { x = x*2;} //just example function
};
And another class that modify and use data from the previous
class Foo {
A a;
public:
Foo::Foo(A &a_) : a(a_) {}
};
now I create the objects, and passes to the Foo class
B b;
// edit b attributes,
Foo foo(b);
So at the argument list for the class constructor I know there is not the problem of object slicing, because is a reference, but what is the case at the moment of assign the variable a(a_)?
Since I don't know how much time the object b is going to live I need to make a secure copy. I have a lot of different derived classes from A, even derived from the derived.
Will there be a object slicing?,
Is there a solution to this, or I need to pass pointers (don't want this approach)?
This causes slicing. C++ built in polymorphism only works with pointer/reference semantics.
In fact:
class Foo {
A a;
that won't even compile, because A is not a concrete class.
To fix this, first make virtual ~A(){}; and then pass smart pointers to A around. Either unique or shared.
Failing that you can use your own bespoke polymorphism. The easiers way is to stuff a pImpl smart pointer as a private member of a class and implement copy/move semantics in the holding class. The pImpl can have a virtual interface, and the wrapping class just forwards the non-overridable part of the behaviour to it.
This technique can be extended with the small buffer optimization, or even bounded size instances, in order to avoid heap allocation.
All of this is harder than just using the built in C++ object model directly, but it can have payoff.
To see a famous example of this, examine std::function<Sig> which is a value type that behaves polymorphically.
There will be object slicing with what you currently have. You're calling the A copy-constructor in Foo's constructor, and there aren't virtual constructors.
Having a member variable of type A only reserves enough space within an instance of Foo for an instance of A. There is only dynamic binding with pointers and references (which are pointers under the hood), not with member variables.
You would have to use pointers to get around this or you could rethink whether you really need a set-up like this.
Yes, there is slicing.
There has to be slicing, because a B does not fit inside a A, but it is an A that you are storing inside the class Foo. The B part is "sliced off" to fit; hence the name.
I'm currently trying to make a pair of classes which depend on each other. Essentially, objects of class B create objects of class A. However, I am also using an inheritance hierarchy, so all derivatives of class B must also be able to create derivatives of class A (each derivative of B corresponds to a derivative of A, so DerB1 makes DerA1 objects, and DerB2 makes DerA2 objects).
I'm having problems with my implementation, and it may be silly, but I would like to see if anyone knows what to do. My code is below (I HATE reading other people's code, so I tried to make it as easy to read as possible...only a few important bits, which I commented to explain)
class BaseB {} // Declare BaseB early to use in BaseA constructor
class BaseA
{
public:
BaseA(BaseB* b) {}; // Declare the BaseA constructor (callable by all B classes, which pass a pointer to themselves to the constructor so the A objects can keep track of their parent)
}
class DerA:public BaseA
{
DerA(BaseB* b):BaseA(b) {}; // Inherit the BaseA constructor, and use initialization list
}
class BaseB
{
public:
virtual BaseA createA() = 0; // Virtual function, representing method to create A objects
}
class DerB:public BaseB
{
BaseA createA() {
DerA* a = new DerA(this); // Definition of createA to make a new A object, specifically one of type DerA (Error1: No instance of constructor "DerA::DerA" matches the argument list)
return a; // Error2: Cannot return DerA for BaseA function
}
}
So, I have two main problems, one is practical (Error1, as I seem to simply be calling the function wrong, even if I try to typecast this), one is philosophical (Error 2, as I don't know how to implement the features I want. If anyone could point out why Error1 is occurring, that would be wonderful! Error2, however, requires some explanation.
I would like my user (programmer) to interact with all A objects the same way. They will have the same exact public functions, but each will have VERY different implementations of these functions. Some will be using different data types (and so will require function contracts), but many will have the same data types just with different algorithms that they use on them. I would like some piece of code to work exactly the same way if one class A derivative is used or another is. However, in my current implementation, it seems that I need to return a DerA object instead of a BaseA object (at the site of Error2). This means that I will need to write a segment of main code SPECIFICALLY for a DerA object, instead of any arbitrary A object. I would like something like:
BaseB b = new DerB(); // Declare which derivative of BaseB I want to use
BaseA a = b->createA(b); // Call the createA function in that derivative, which will automatically make a corresponding A object
This way, I can simply choose which type of B object I would like in the first line (by my choice of B constructor, or tag, or template, or something), and the rest of the code will look the same for any type of object B (as each has the same public member functions, even though each object will perform those functions differently).
Would I be better off using templates or some other method instead of inheritance? (I apologize for being intentionally vague, but I hope my class A/B example should mostly explain what I need).
Thank you for any help. I apologize for asking two questions in one post and for being long-winded, but I am trying to learn the best way to approach a rather large redesign of some software.
You have several syntactical issues to get the errors solved:
Add the ; after each class definitions.
The first line should be a forward declaration: class BaseB /*{} NO!!*/ ;
Add public: to make constructor of DerA accessible for DerB
BaseA createA() should return a value, not a pointner (according to signature): return *a;
There is another potential hidden slicing issue, as createA() returns a value, an not a pointer. This means that your returned object (here *a), would be copied but as a real BaseA object. So only the BaseA part of the object will be copied, not the derived part. This could lead to some unexpected surprises.
In order to avoid slicing, consider returning a pointer, changing the signature of createA() accordingly. The object pointed to would then keep the right type without loosing anything.
If you would later need to copy the object, you could use a static cast if you are absolutely sure of the real type of the object pointed to:
BaseA *pba = pdb->createA(); // get pointer returned
DerA da = *static_cast<DerA*>(pba); // static cast with pointer
If you would need to copy pointed BaseA objects without necessarily knwowing for sure their real type, you could implement a virtual clone function in DerA (e.g. prototype design pattern)
Objective-C category feature allows programmer to add new method which was not defined in original class definition.
Can I archive similar functionality (language construct or some technique) on C++?
Major concern is consistent method calling syntax (. or -> operator).
Let's consider the following class to be extended:
struct A {
int x, y;
A(int x, int y) : x(x), y(y) {}
};
You can inherit from this class or write a wrapper class which contains an instance of this class. In most cases, inheritance is the way to go, as a wrapper class isn't an A but it wraps (contains) an A.
With C++11 move semantics, promoting an instance A to a subclass B (inheriting A) will be efficient and doesn't require to copy the instance A:
class B : public A {
public:
B (A &&a) : A(a), someOtherMember(a.x + a.y) {}
// added public stuff:
int someOtherFunction() const { return someOtherMember; }
private:
// added private stuff:
int someOtherMember;
};
Full code with example: http://ideone.com/mZLLEu
Of course the function I added is a bit silly (and the member even more, since it doesn't respect further changes of the original members x and y), but you should get an idea of what I want to demonstrate.
Note the constructor B (A &&a) which is something I call "promote constructor" (this is not a standard term). Normally, B (B &&b) is a move constructor, which moves the contents of the provided B instance into a new B about to be constructed. I use the move semantics to move an instance of A (which has been returned by another function) into the super-class A of B.
Effectively, you can promote A to B while making it possible to use a B as an A.
In contrast to Soonts' answer, my solution also works with added virtual tables, since it doesn't rely on unsafe pointer casting.
Another option, which may not be viewed as "clean" by some (though it is in my opinion) but still accomplishes the same thing, is using a static class. It's important to remember that when we create a member function, what's really happening behind the scenes is that the compile generates a function where the object (aka "this") is the first parameter. So, we can do the same thing to extend our class's functionality without deriving from it.
class Something
{
public:
Something()
~Something()
}
// In objective-c you may call this category Something+Utils
class SomethingUtils
{
// You can use a pointer, or a reference here, your call.
static int GetSomethingElse(Something *something, int parameter);
}
This will accomplish the same intent as a category: You extend the functionality of your class object, and you don't have to create a new derived class. You will not be able to access private or protected member functions and variables, but you can't do that in objective-c anyway, so there's nothing lost on that front (and if you are trying to use private or protected member state, you've missed the point of categories entirely). You wouldn't be able to use the . and -> operators, but in my opinion, that's a much better compromise than deriving a new type just to add some utility methods.
C++ has the inheritance for that. In addition, I've used the following trick a few times to extend classes generated by #import "progid:..." directive:
// This one is part of external framework, or auto-generated, or dllimport, or #import, etc..
class A
{
protected double m_x;
};
// This one is the extension class. Make sure you only add non-virtual methods here.
// Static methods and static data members are OK as well.
class __declspec( novtable ) B: public A
{
public:
double getSquare(){ return m_x * m_x; }
__declspec( property( get = getSquare ) ) double square;
};
// Usage example
double someFunc( A& arg )
{
B& b = static_cast<B&>( arg ); // Note we've not constructed any instance of B, just casted.
return b.square;
}
I got a nearly consistent calling convention with an idea I talked about in a lightning talk a year or so ago:
(the intro makes less sense without he commentary - wait til it gets to the C++ bit).
Note that the material was not intended to be taken seriously - although some, inevitably, have ;-)
I am using OGRE and I have run into an issue that is not so much specific to ORGE, but is a genreal C++ issue I am dealing with. ORGE just helps with the context of the question.
There is a macro that is something such as
OGRE_DELETE_T(obj, ExternalClass);
However, in order for delete to be called, I need to pass in the type of the class as the second parameter. However, say for instance I have a base class A, then class B, class C, class D, etc. If I were to store a std::vector of just A pointers, but in actuality I may have instantiated them as B, C, or some deriviative of A, how could I pass the type of the actual class constructed into this macro? I do not know what type the derived object is when I go to delete it, all I know is there is class A pointers.
I thought perhaps using dynamic_cast, however, I did not like the runtime performance and I would also need to have some sort of a lookup table of types to check against.
Just pass the type of the derived object in the macro. It will delete your pointer properly, if your base has a virtual destructor.
I know this question is old, but this answer might help others.
This macro is used to track your memory and if you need to use it on your derived types, you will have to compromise the interface a bit. One way you could do it is to create a virtual function that deletes the object appropriately. You do have to call specific destruction macro anyways when using OGRE_ALLOC_T or OGRE_NEW_T so the user could be aware of this special case.
class Parent
{
public:
virtual void deleteSelf() = 0;
};
class A : public Parent
{
public:
virtual void deleteSelf()
{
A* p = this;
OGRE_DELETE_T(p, A);
}
};
This way you can delete it this way:
Parent* p = OGRE_NEW_T(A);
p->deleteSelf();