A class like
class A{
public:
const B& instanceOfB ;
A(const B& someInstanceOfB):
instanceOfB(someInstanceOfB)
{
};
// some methods depending on instanceOfB here
};
should be extended to provide also some methods which do not depend on instanceOfB, and these methods must be accessible without any instanceOfB (i.e., no instance of B may exist at all).
Hence, a straight forward extension could look like
class A{
public:
B* const instanceOfB ;
A():
instanceOfB(nullptr)
{
}
// some methods not depending on instanceOfB here
void assignInstanceOfB(B* const someInstanceOfB){
instanceOfB = someInstanceOfB;};
// some methods depending on instanceOfB here
};
However, in my opinion, this has several disadvantages:
The original version of the class was easy to use, while for the extended version it must be ensured that assignInstanceOfB is called prior to any other method depending on instanceOfB
Basically, any method depending on instanceOfB must check if the initialization was perfomed. This produces a huge (i.e., ugly) overhead.
A nullptr initialization is used, which seems to be bad practice in my opinion. I generally try to avoid any pointers.
So i am not really satisfied by this design. What could look a more sophisticated version look like? Thank you!
Edit: Due to the comments, i add following additional requirements:
- Splitting of the class is not possible
- The reference to B must be stored, it is not possible to hand it only to the respective methods.
To summarize, it seems that using pointers (including smart pointers) is the recommended or at least usual way.
To address your first concern about having to call the initialize function before the object can be used, you could implement two constuctors. One would take in a pointer to B and the other defaults to nulling the pointer.
class A{
public:
B* const instanceOfB ;
A(B* const b) : instanceOfB(b) { }
A() : A(nullptr) { }
};
In regards to your third concern, using non-owning pointers is the usual way to store a reference to an object that may or may not exist. If you are hell-bent on not using pointers you could use std::optional in a manner such as this:
class A
{
public:
std::optional<std::reference_wrapper<B>> instanceOfB;
A(B * const b = nullptr) : instanceOfB(std::nullopt)
{
if (b != nullptr)
{
instanceOfB = std::make_optional(std::ref(*b));
}
}
void doSomething()
{
if (!instanceOfB)
{
return;
}
instanceOfB->get().something();
}
};
You need to use std::reference_wrapper since std::optional explicitly does not support storing references directly. You'll still need to check if the optional contains anything before using it, so you still end up needing code that's very similar to checking for a null pointer. There's even worse syntax to access the inner reference, as can be seen in doSomething(). In the end this doesn't seem like it gains you anything, and I wouldn't recommend it.
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
Have seen some related questions, but not this exact one...
I've treated classes as fitting into a few major categories, let's say these four for simplicity:
Value Classes which have some data and a bunch of operations. They can be copied and meaningfully compared for equality (with copies expected to be equal via ==). These pretty much always lack virtual methods.
Unique Classes whose instances have identity that you disable assignment and copying on. There's usually not an operator== on these because you compare them as pointers, not as objects. These quite often have a lot of virtual methods, as there isn't risk of object-slicing since you're being forced to pass them by pointer or reference.
Unique-but-Clonable Classes which disable copying, but are pre-designed to support cloning if that's what you really want. These have virtual methods, most importantly those following the virtual construction / cloning idiom
Container Classes which inherit the properties of whatever they're holding. These tend not to have virtual methods...see for instance "Why don't STL containers have virtual destructors?".
Regardless of holding this informal belief system, a couple times I've tried adding a virtual method to something copyable. While I may have thought it would "be really cool if that worked", inevitably it breaks.
This led me to wonder if anyone has an actual good example of a type which has virtual methods and doesn't disable copying?
The only counter-example that I have are classes that are meant to be stack-allocated and not heap-allocated. One scheme I use it for is Dependency Injection:
class LoggerInterface { public: virtual void log() = 0; };
class FileLogger final: public LoggerInterface { ... };
int main() {
FileLogger logger("log.txt");
callMethod(logger, ...);
}
The key point here is the final keyword though, it means that copying a FileLogger cannot lead to object-slicing.
However, it might just be that being final turned FileLogger into a Value class.
Note: I know, copying a logger seems weird...
There's nothing inherently wrong in being able to copy a polymorphic class. The problem is being able to copy a non-leaf class. Object slicing will get you.
A good rule of thumb to follow is never derive from a concrete class. This way, non-leaf classes are automatically non-instantiable and thus non-copyable. It won't hurt to disable assignment in them though, just to be on the safe side.
Of course nothing is wrong with copying an object via a virtual function. This kind of copying is safe.
Polymorphic classes are normally not "value-classes" but it does happen. std::stringstream comes to mind. It'not copyable, but it is movable (in C++11) and moving is no different from copying with regard to slicing.
Virtual dispatch happens a runtime. The only reason one should want it is when the actual, dynamic type of an object cannot be known until runtime. If you already knew the desired dynamic type when writing the program, you could use different, non-virtual techniques (such as templates, or non-polymorphic inheritance) to structure your code.
A good example for the need for runtime typing is parsing I/O messages, or handling events – any kind of situation where one way or another you'll either have some sort of big switch table to pick the correct concrete type, or you write your own registration-and-dispatch system, which basically reinvents polymorphism, or you just use virtual dispatch.
(Let me interject a warning: Many people misuse virtual functions to solve problems that don't need them, because they're not dynamic. Beware, and be critical of what you see.)
With this said, it's now clear that your code will be dealing mostly with the polymorphic base classes, e.g. in function interfaces or in containers. So let's rephrase the question: Should such a base class be copyable? Well, since you never have actual, most-derived base objects (i.e. the base class is essentially abstract), this isn't really an issue, and there's no need for this. You've already mentioned the "clone" idiom, which is the appropriate analogue of copying in a polymorphic.
Now, the "clone" function is necessarily implemented in every leaf class, and it necessarily requires copying of the leaf classes. So yes, every leaf class in a clonable hierarchy is a class with virtual functions and a copy constructor. And since the copy constructor of a derived class needs to copy its base subobjects, all the bases need to be copyable, too.
So, now I believe we've distilled the problem down to two possible cases: Either everything in your class hierarchy is completely uncopyable, or your hierarchy supports cloning, and thus by necessity every class in it is copyable.
So should a class with virtual functions have a copy constructor? Absolutely. (This answers your original question: when you integrate your class into a clonable, polymorphic hierarchy, you add virtual functions to it.)
Should you try to make a copy from a base reference? Probably not.
Not with a single, but with two classes:
#include <iostream>
#include <vector>
#include <stdexcept>
class Polymorph
{
protected:
class Implementation {
public:
virtual ~Implementation() {};
// Postcondition: The result is allocated with new.
// This base class throws std::logic error.
virtual Implementation* duplicate() {
throw std::logic_error("Duplication not supported.");
}
public:
virtual const char* name() = 0;
};
// Precondition: self is allocated with new.
Polymorph(Implementation* self)
: m_self(self)
{}
public:
Polymorph(const Polymorph& other)
: m_self(other.m_self->duplicate())
{}
~Polymorph() {
delete m_self;
}
Polymorph& operator = (Polymorph other) {
swap(other);
return *this;
}
void swap(Polymorph& other) {
std::swap(m_self, other.m_self);
}
const char* name() { return m_self->name(); }
private:
Implementation* m_self;
};
class A : public Polymorph
{
protected:
class Implementation : public Polymorph::Implementation
{
protected:
Implementation* duplicate() {
return new Implementation(*this);
}
public:
const char* name() { return "A"; }
};
public:
A()
: Polymorph(new Implementation())
{}
};
class B : public Polymorph {
protected:
class Implementation : public Polymorph::Implementation {
protected:
Implementation* duplicate() {
return new Implementation(*this);
}
public:
const char* name() { return "B"; }
};
public:
B()
: Polymorph(new Implementation())
{}
};
int main() {
std::vector<Polymorph> data;
data.push_back(A());
data.push_back(B());
for(auto x: data)
std::cout << x.name() << std::endl;
return 0;
}
Note: In this example the objects are copied, always (you may implement shared semantics, though)
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 ;-)
As far as I know, you cannot inherit constructors in C++. But there are situations, where it might be required that it looks like you can instantiate inherited classes the same way you instantiate their base:
struct Base {
int i;
int const j;
Base(int i, int j) : i(i), j(j) {}
};
// option 1)
struct Derived1 : Base {
Derived1(int i, int j) : Base(i,j) {}
};
Base* baseFactory() {
return new Derived1(42,47);
}
// option 2)
struct Derived2 : Base {
};
Base* baseFactory() {
Base* b = new Derived2();
b->i = 42;
b->j = 47; // broken!
// alternative could be to implement Base::operator=
return b;
}
Note that the derived classes could be default constructed if it weren't for their base class(es).
Option 1 is what is usually done, I think, but you are typing code without expressing anything new. Option 2 breaks const correctness (and prevents you from using references as members) because everything must be assignable.
Is there a nice way around this?
Edit: C++11 is great, but unfortunately I need a C++03 solution.
Option 1 is the idiomatic way in C++03, it does require more typing, but that is how the language is. Option 2 is not even close to equivalent, you would not be able to initialize Derived2 as Base does not have a default constructor, and the definition of the implicitly declared default constructor for Derived2 needs it.
But beyond the technical difficulty in the language you are trading construction for two-phase construction which is never a good idea, and at the same time forcing your use of Derived2 to dynamically allocated objects.
There is an alternative approach:
// option 3)
struct Derived3 : Base {
Derived3(const Base &b) : Base(b) {}
};
Base* baseFactory3() {
return new Derived3(Base(42,47));
}
This may not be a good idea if constructing a full Base object is expensive or requires external resources. In that case you could create a light-weight object that carries constructor arguments for Base, so that instead of multiple Base constructors you have multiple BaseArguments constructors, and one Base constructor that takes in BaseArguments. However I don't think many people would consider that good style in most circumstances.
C++11 supports inherited constructors.
http://en.wikipedia.org/wiki/C%2B%2B11
However not all compilers that supports now a subset of C++11 supports all functionalities.
Microsoft visual C++ 2010 supports several new C++0x features but not inherited constructors, here is a list: http://blogs.msdn.com/b/vcblog/archive/2010/04/06/c-0x-core-language-features-in-vc10-the-table.aspx
GCC supports more new features but not the inherited constructors. See http://gcc.gnu.org/projects/cxx0x.html
To enable GCC to compile with C++0x features you need to add -std=c++0x or -std=gnu++0x compilation parameter.
Visual C++ 2010 have these enabled by default.
You just need to wait :)
There are not clean solutions for previous version of the standard, for this reason it was introduced in C++11, because it was not possible to do with previous versions.
So, the only thing you can do, is to copy your constructors and call base constructor.
Here' a variation on the Builder Pattern that I always thought it could be useful, but I never actually got a chance to use it; I guess you could call it the Constructor Pattern. :P
It also offers some other advantages, like not having to specify arguments in a certain order: you only specify what you are interested in and in whatever order you want.
I still think this is justified only if your class has lots of constructors with different parameters. Otherwise, it's just an annoyance.
class Person
{
public:
class Constructor;
};
class Person::Constructor
{
public:
Constructor& name(const std::string&);
Constructor& age(int);
Person* make();
};
Person* pers = Person::Constructor()
.name("Bob Marley").make();
class Employee : public Person
{
public:
class Constructor;
};
class Employee::Constructor : public Person::Constructor
{
public:
Constructor& salary(double);
Employee* make();
};
Employee* emp = Employee::Constructor()
.name("Emilly Smith").age(23).make();
But again, this is justifiable only if your class has lots of constructors with lots of parameters and you want to avoid having to write multiple overloads to those; otherwise, this just adds too much complexity without any real benefit.
I mentioned I don't like han's proposed solution. This is because (1) you are moving the need to (re)declare a number of constructors in the child class to the need to place the same number of functions inside a factory class; (2) it is hacky and the intent is not explicit; and (3) you could view this as a violation of dependency injection.
Is there any way to declare these classes in a header file without indirection?
// Forwards declaration of B
class B;
class A
{
public:
// Default parameter referring to B. May return its parameter
const B& func(const B& b = B());
};
class B
{
public:
// B ctors
B() {}
B(const B&) {}
// B has A as a member
A a;
};
Visual C++ 2008 tells me with this:
error C2514: 'B' : class has no constructors
and points to the forward declaration of B ("class B;") and obviously can't see B's constructors below. A can't follow B because B contains A as a member.
If indirection must be used, what's the best way? Perhaps in C++0x B's A could be a unique_ptr member? Or maybe there's a boost class purely to sidestep this issue?
Instead of a default parameter declare two overloads, one that takes a B by reference and one that takes no parameter. In the one that takes no parameter, call the other with B(), which will work because that method can be defined after B is defined.
...
void func();
void func(const B& b);
};
class B...
void A::func() { func(B()); }
void A::func(const B&) { }
Update:
func() returns a const B&...
That's probably not a good idea. With that definition, something like:
const B& foo = a.func();
foo.bar();
would cause the dreaded "undefined behavior" (i.e., crash) because the B to which you have a reference will be destroyed as soon as the first statement is complete. Returning things other than class members by reference is usually a bad idea.
If you really want to do this, then I think you're stuck with forcing the caller to explicitly pass in B(), that is have no default parameter.
a.func(B()).bar();
(This is the only way to avoid undefined behavior with such a function.)
Of course you could just return a copy instead of a reference, but I presume you have a reason for not doing that.
Depending on what you're doing you may be able to set up better semantics using a smart pointer like shared_ptr instead of references so that you can effectively ignore the lifetimes of the objects. You then have to start being careful of reference cycles instead, however.
I can't tell what you're trying to use this for, but you might want to have a look at some Design Patterns to see if there is an established best-practice for it. You may find that this little problem is a symptom of an unfortunate choice of class structure or containment.