EDIT:
In the following code container::push takes an object of type T that derives from base as argument and stores in a vector a pointer to the method bool T::test().
container::call calls each of the stored methods in the context of to the member object p, which has type base, not T. It works as long as the called method does not refer to any member outside base and if test() is not declared virtual.
I know this is ugly and may not be even correct.
How can I accomplish the same thing in a better way?
#include <iostream>
#include <tr1/functional>
#include <vector>
class base {
public:
base(int v) : x(v)
{}
bool test() const { // this is NOT called
return false;
}
protected:
int x;
};
class derived : public base {
public:
bool test() const { // this is called instead
return (x == 42);
}
};
class container {
public:
container() : p(42)
{}
template<typename T>
void push(const T&) {
vec.push_back((bool (base::*)() const) &T::test);
}
void call() {
std::vector<bool (base::*)() const>::iterator i;
for(i = vec.begin(); i != vec.end(); ++i) {
if( (p .* (*i))() ) {
std::cout << "ok\n";
}
}
}
private:
std::vector<bool (base::*)() const> vec;
base p;
};
int main(int argc, char* argv[]) {
container c;
c.push(derived());
c.call();
return 0;
}
What you are doing with your "boost::bind" statement is to call derived::test and pass "b" as a "this" pointer. It's important to remmember that the "this" pointer for derived::test is supposed to be a pointer to a "derived" object - which is not the case for you. It works in your particular situation since you have no vtable and the memory layout is identical - but as soon as that will change, your program will likely break.
And besides, it's just plain wrong - ugly, unreadable, bug-prone code. What are you really trying to do?
[Edit] New answer to the edited question: You should use boost::bind to create a functional closure, that wraps both the object & the member function in a single object - and store that object in your collection. Then when you invoke it, it is always reliable.
If you can't use boost in your application... well, you could do something like boost::bind yourself (just look on how it is done in boost), but it's more likely that you'll get it wrong and have bugs.
To the updated question:
Calling a derived member function on a base object is Undefined Behavior. What you are trying to achieve (code) is wrong. Try to post what you need and people will help with a sensible design.
What you are doing is not correct, and in the simple example it will work, but might just raise hell (one of the possibilities for undefined behavior) in other cases.
Since base::test and derived::test are not virtual, they are two different member methods, so for simplicitly I will call them base::foo and derived::bar. In the binder code you are forcing the compiler into adapting a pointer to bar that is defined in derived as if it was actually defined in base and then calling it. That is, you are calling a method of derived on an object or type base!!! which is undefined behavior.
The reason that it is not dying is that the this pointers in base and derived coincide and that you are only accessing data present in the base class. But it is incorrect.
When you declare base::test virtual, you get the correct behavior: your most derived object in the hierarchy is base, the compiler will use the virtual dispatch mechanism and find out that base is where the final overrider for test is found and executed.
When you declare only derived::test as virtual (and not base) the compiler will try to use an inexistent virtual dispatch mechanism (usually a vtable pointer) in the handed object and that kills the application.
At any rate, all but the virtual base::test uses are incorrect. Depending on what your actual requirements are, the most probably correct way of doing it would be:
class base {
public:
virtual bool test() const;
};
class derived : public base {
public:
virtual bool test() const; // <--- virtual is optional here, but informative
};
int main()
{
derived d; // <--- the actual final type
base & b = d; // <--- optional
if ( std::tr1::bind( &base::test, std::tr1::ref(b))() ) {
// ...
}
}
Note that there is no cast (casts are usually a hint into something weird, potentially dangerous is hiding there), that the object is of the concrete type where you want the method to be called, and that the virtual dispatch mechanism guarantees that even if the
bind is to base::test, as the method is virtual, the final overrider will be executed.
This other example will more likely do funny things (I have not tried it):
struct base {
void foo() {}
};
struct derived : base {
void foo() {
for ( int i = 0; i < 1000; ++i ) {
std::cout << data[i];
}
}
int data[1000];
};
int main() {
base b;
std::tr1::bind((void (base::*)()) &derived::foo, std::tr1::ref(b))();
}
Related
class Base {};
class Derived : public Base {};
void func(boost::optional<Base>&) {}
int main () {
boost::optional<Derived> x;
func(x);
}
will func accept both optionals: base and derived?
No, it won't work. func takes an lvalue reference to boost::optional<Base>. That means it can accept an lvalue of type boost::optional<Base>, an lvalue of a type that derives publicly and unambiguously from boost::optional<Base>, or some other type that has an operator boost::optional<Base>&(). None of those is true of boost::optional<Derived>. Class templates are not coviarant in the C++ type system - boost::optional<Derived> does not inherit from boost::optional<Base>.
It would be a different story if func took its argument by value. If it looked like:
void func(boost::optional<Base> ) { }
In that case, you could call func with a boost::optional<Derived>. But that converting constructor is marked explicit, so you would have to write:
func(boost::optional<Base>{x});
It's good that this is explicit - you are marking clear that you are (potentially) slicing x.
Even if it would work (which is likely buy I haven't checked) it would cause slicing. Only Base part would be stored in optional.
optional keeps internally a buffer of the size needed to store Base. And even if Base would be of the same size as Derived (as in your case) still it would store only Base.
EDIT:
Above answer was given for the original question which contained following code:
int main () {
boost::optional x(Derived());
func(x);
}
Such code is not correct because of two reasons:
boost::optional requires template argument
Even with the template argument it would still be function declaration.
I have ignored those issues and assumed that something like this was meant:
int main () {
boost::optional<Base> x = Derived();
func(x);
}
While that code does compile (at least Visual Studio 2013 and Boost 1.60) and causes slicing. As can be seen by running following program:
#include <boost/optional.hpp>
#include <iostream>
class Base
{
public:
virtual ~Base() { std::cout << "~Base" << std::endl; }
};
class Derived : public Base
{
public:
virtual ~Derived() { std::cout << "~Derived" << std::endl; }
};
int main()
{
boost::optional<Base> x = Derived();
}
which produces output
~Derived
~Base
~Base
The second ~Base shows that optional destroyes Base object rather than Derived object. (The ~Derived is from the temporary object Derived() as is the first ~Base.)
I have a class that contains some functions (none are virtual) and 2 more classes publicly inherit that class. In both the sub classes I override the same function of the base class.
After creating objects of all three classes in main (located at the same file), I call the original function with the baseclass object and the overridden functions with the derivedclass objects.
I was expecting all 3 function calls to run the original function from the base class (since I didn't use 'virtual' anywhere in the code), but I actually get each version of that function working according to the class in which it was defined (3 different versions).
I have the classes Base & Derived as follows:
struct Base
{
void foo();
};
struct Derived : Base
{
void foo();
};
in main:
int main()
{
Derived d;
d.foo();
}
I thought d.foo() should run Base::foo() if not using 'virtual'.
This is not "overriding"... and it doesn't need to be.
struct Base
{
void foo();
};
struct Derived : Base
{
void foo();
};
int main()
{
Derived d;
d.foo();
}
If I understand you correctly, then you were expecting this to execute Base::foo(), because the functions are not virtual and therefore one does not override the other.
But, here, you do not need virtual dispatch: the rules of inheritance simply state that you'll get the right function for the type of the object you run it on.
When you need virtual dispatch/overriding is a slightly different case: it's when you use indirection:
int main()
{
Base* ptr = new Derived();
ptr->foo();
delete ptr;
}
In the above snippet, the result will be that Base::foo() is called, because the expression ptr->foo() doesn't know that *ptr is really a Derived. All it knows is that ptr is a Base*.
This is where adding virtual (and, in doing so, making the one function override the other) makes magic happen.
You cannot override something that isn't virtual. Non-virtual member functions are dispatched statically based on the type of the instance object.
You could cheat by "overriding" a function by making it an inline function calling something indirectly. Something like (in C++03)
class Foo;
typedef int foo_sig_t (Foo&, std::string&);
class Foo {
foo_sig_t *funptr;
public:
int do_fun(std::string&s) { return funptr(*this,s); }
Foo (foo_sig_t* fun): funptr(fun) {};
~Foo () { funptr= NULL; };
// etc
};
class Bar : public Foo {
static int barfun(Bar&, std::string& s) {
std::cout << s << std::endl;
return (int) s.size();
};
public:
Bar () : Foo(reinterpret_cast<foo_sig_t*>)(&barfun)) {};
// etc...
};
and later:
Bar b;
int x=b.do_fun("hello");
Officially this is not overloading a virtual function, but it looks very close to one. However, in my above Foo example each Foo instance has its own funptr, which is not necessarily shared by a class. But all Bar instances share the same funptr pointing to the same barfun.
BTW, using C++11 lambda anonymous functions (internally implemented as closures), that would be simpler and shorter.
Of course, virtual functions are in generally in fact implemented by a similar mechanism: objects (with some virtual stuff) implicitly start with a hidden field (perhaps "named" _vptr) giving the vtable (or virtual method table).
I would like to force a certain API for all classes derived from the base class. Normally, you do that using an abstract base class that has purely virtual functions. However, how do you handle functions that return the derived type? How do I go about forcing that type of function?
struct base
{
virtual base func() = 0;
};
struct deriv1 : base
{
deriv1 func();
};
struct deriv2 : base
{
deriv2 func();
};
This example will give an error like "invalid abstract return type for member function". I've seen some answers that suggest returning pointers, but I don't particularly want to dip into dynamic memory for that and keeping track of all the allocated pointers would be a special kind of hell. Any ideas?
When a virtual function returns a pointer or reference to a class, a class which inherits from the base class and overrides the function is allowed to change the return type to a pointer or reference to a class which is derived from the original return type.
You can't return base by value as it is abstract so you can't actually create one by itself.
http://en.wikipedia.org/wiki/Covariant_return_type
When using virtual functions and base classes, you usually have to use dynamic allocation to create your objects. I suggest you look into smart pointers to help manage the memory.
In your example, the func won't be "the same function", so the deriv1 and deriv2 variants won't have a different virtual function.
Unfortunately, there is no other alternative than to return a pointer - it doesn't have to be a pointer to dynamically allocated memory (you could for example return a pointer to this or a static deriv2 anObject; - but it needs to be a pointer to base. [Or a reference, but the same problem applies].
The main reason for this (aside from the fact that "functions can't be differentiated only on return type") is that if you have some generic code that looks something like this:
vector<base*> v;
... stuff a bunch of `dervi1` or `deriv2` objects into v.
for(i : v)
{
base b = i->func();
}
Now, either you have now cut off [sliced] your deriv1 or deriv2 into the size of a base, or you'd have copied an object that is larger than base into a base-size object - neither of which will be of any benefit whatsoever. [I'm assuming that in the REAL use-case for this, deriv1 and deriv2 are in fact different from base by more aspects than the name of the object - otherwise, it's quite pointless. And that deriv1 and deriv2 are inheriting from base, of course].
In other words, you can't copy an object of unknown type with =. And it's absolutely no point in having a virtual function if you have to know what type it returns.
Basically a way of saying "If you want to replace deriv1 with deriv2 in your code, you need to implement these functions"
From your quote here above, it looks like you want something like this:
#include <memory> //for unique_ptr
#include <iostream>
struct Base
{
virtual void doX() = 0;
virtual void doY() = 0;
virtual ~Base(){}
};
struct D1 : Base
{
virtual void doX()
{
std::cout << "D1::doX()" << std::endl;
}
virtual void doY()
{
std::cout << "D1::doY()" << std::endl;
}
};
struct D2 : D1
{
virtual void doX()
{
std::cout << "D2::doX()" << std::endl;
}
virtual void doY()
{
std::cout << "D2::doY()" << std::endl;
}
};
//From this point on you can do various things:
void driver()
{
Base* base = new D1;//
base->doX(); //Calls D1::doX()
D1* d1 = new D2;
d1->doX(); //Calls D2::doX()
}
// or...
void driver( Base* base )
{
//A way to replace Base with D1 with D2 depending
// on how driver was called.
}
//Finally, maybe you want a factory to create the correct
// derived type based on which factory was instantiated.
// Creates family of products, each item representing the base
// in it's hierarchy - only one shown here...
struct AbstractFactory
{
virtual std::unique_ptr<Base> create() const = 0;
protected:
virtual ~AbstractFactory(){}
};
struct D1Factory : AbstractFactory
{
//Doesn't matter if <Derived> is returned, because it adheres
// to interface of Base (isA base), and correct functions are
// found polymorphically
virtual std::unique_ptr<Base> create() const
{
return std::unique_ptr<Base>( new D1 );
}
};
struct D2Factory : AbstractFactory
{
//Doesn't matter if <Derived> is returned, because it adheres
// to interface of Base (isA base), and correct functions are
// found polymorphically
virtual std::unique_ptr<Base> create() const
{
return std::unique_ptr<Base>( new D2 );
}
};
void driver( const AbstractFactory& factory )
{
std::unique_ptr<Base> base( factory.create() );
base->doX();
base->doY();
//Memory deallocated automagically...
}
int main()
{
driver( D1Factory() );
driver( D2Factory() );
}
You'll see that this holds true to your quote. D2 replaces D1
seamlessly from the perspective of driver...
I have the following code (stolen from virtual functions and static_cast):
#include <iostream>
class Base
{
public:
virtual void foo() { std::cout << "Base::foo() \n"; }
};
class Derived : public Base
{
public:
virtual void foo() { std::cout << "Derived::foo() \n"; }
};
If I have:
int main()
{
Base base;
Derived& _1 = static_cast<Derived&>(base);
_1.foo();
}
The print-out will be: Base::foo()
However, if I have:
int main()
{
Base * base;
Derived* _1 = static_cast<Derived*>(base);
_1->foo();
}
The print-out will be: Segmentation fault: 11
Honestly, I don't quite understand both. Can somebody explain the complications between static_cast and virtual methods based on the above examples? BTW, what could I do if I want the print-out to be "Derived::foo()"?
A valid static_cast to pointer or reference type does not affect virtual calls at all. Virtual calls are resolved in accordance with the dynamic type of the object. static_cast to pointer or reference does not change the dynamic type of the actual object.
The output you observe in your examples is irrelevant though. The examples are simply broken.
The first one makes an invalid static_cast. You are not allowed to cast Base & to Derived & in situations when the underlying object is not Derived. Any attempt to perform such cast produces undefined behavior.
Here's an example of valid application of static_cast for reference type downcasting
int main()
{
Derived derived;
Base &base = derived;
Derived& _1 = static_cast<Derived&>(base);
_1.foo();
}
In your second example the code is completely broken for reasons that have nothing to do with any casts or virtual calls. The code attempts to manipulate non-initialized pointers - the behavior is undefined.
In your second example, you segfault because you did not instanciate your base pointer. So there is no v-table to call. Try:
Base * base = new Base();
Derived* _1 = static_cast<Derived*>(base);
_1->foo();
This will print Base::foo()
The question makes no sense, as the static_cast will not affect the v-table. However, this makes more sens with non-virtual functions :
class Base
{
public:
void foo() { std::cout << "Base::foo() \n"; }
};
class Derived : public Base
{
public:
void foo() { std::cout << "Derived::foo() \n"; }
};
int main()
{
Base base;
Derived& _1 = static_cast<Derived&>(base);
_1.foo();
}
This one will output Derived::foo(). This is however a very wrong code, and though it compiles, the behavior is undefined.
The whole purpose of virtual functions is that the static type of the variable shouldn't matter. The compiler will look up the actual implementation for the object itself (usually with a vtable pointer hidden within the object). static_cast should have no effect.
In both examples the behavior is undefined. A Base object is not a Derived object, and telling the compiler to pretend that it is doesn't make it one. The way to get the code to print out "Derived::foo()" is to use an object of type Derived.
Say I have the following code:
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->foo_impl(); //A
(*static_cast<Derived*>(this)).foo_impl(); //B
}
};
class Derived : public Base<Derived> {
private:
void foo_impl() {
bar();
}
};
A few questions:
Will line A generate a virtual function call? Although the majority of what I can find on the internet recommends doing things this way, to me I don't see how the compiler can do static dispatch considering that a pointer to Derived could still actually point to an object of type Derived2 where Derived2 : public Derived.
Does line B fix the issue I brought up in my previous point (if applicable)? It seems like it would, considering that now the call is not on a pointer any more and thus using *. would avoid a virtual function call. But if the compiler treats the dereferenced cast as a reference type, it could still generate a virtual function call... in that case, what is the workaround?
Does adding the C++11 final keyword to foo_impl() change how the compiler would act in either (or any other relevant) case?
Will line A generate a virtual function call?
Yes. foo_impl() is virtual and Derived overrides it. Even though foo_impl() in Derived is not explicitly tagged as virtual, it is in the base class, and this is enough to make it a virtual function.
Does line B fix the issue I brought up in my previous point (if applicable)?
No. It does not matter if the call is on a pointer or on a reference: the compiler still won't know whether you are invoking the function foo_impl() on an instance of a class that derives from Derived, or on a direct instance of Derived. Thus, the call is performed through a vtable.
To see what I mean:
#include <iostream>
using namespace std;
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->foo_impl();
(*static_cast<Derived*>(this)).foo_impl();
}
};
class Derived : public Base<Derived> {
public:
void foo_impl() {
cout << "Derived::foo_impl()" << endl;
}
};
class MoreDerived : public Derived {
public:
void foo_impl() {
cout << "MoreDerived::foo_impl()" << endl;
}
};
int main()
{
MoreDerived d;
d.foo(); // Will output "MoreDerived::foo_impl()" twice
}
Finally:
Does adding the C++11 final keyword to foo_impl() change how the compiler would act in either (or any other relevant) case?
In theory, yes. The final keyword would make it impossible to override that function in subclasses of Derived. Thus, when performing a function call to foo_impl() through a pointer to Derived, the compiler could resolve the call statically. However, to the best of my knowledge, compilers are not required to do so by the C++ Standard.
CONCLUSION:
In any case, I believe what you actually want to do is not to declare the foo_impl() function at all in the base class. This is normally the case when you use the CRTP. Additionally, you will have to declare class Base<Derived> a friend of Derived if you want it to access Derived's private function foo_impl(). Otherwise, you can make foo_impl() public.
The common idiom for the CRTP does not involve declaring the pure virtual functions in the base. As you mention in one of the comments, that means that the compiler will not enforce the definition of the member in the derived type (other than through use, if there is any use of foo in the base, that requires the presence of foo_impl in the derived type).
While I would stick to the common idiom and not define the pure virtual function in the base, but, if you really feel you need to do it, you can disable dynamic dispatch by adding extra qualification:
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->Derived::foo_impl();
// ^^^^^^^^^
}
};
The use of the extra qualification Derived:: disables dynamic dispatch, and that call will be statically resolved to Derived::foo_impl. Note that this comes will all of the usual caveats: you have a class with a virtual function and paying the cost of the virtual pointer per object, but you cannot override that virtual function in a most derived type, as the use in the CRTP base is blocking dynamic dispatch...
The extra verbiage in lines A and B have absolutely no effect on
the generated code. I don't know who recommends this (I've never seen
it), but in practice, the only time it might have an effect is
if the function isn't virtual. Just write foo_impl(), and be
done with it.
There is a means of avoiding the virtual function call if the
compiler knows the derived type. I've seen it used for
vector-like classes (where there are different implementations,
e.g. normal, sparse, etc. of the vector):
template <typename T>
class Base
{
private:
virtual T& getValue( int index ) = 0;
public:
T& operator[]( int index ) { return getValue( index ); }
};
template <typename T>
class Derived : public Base<T>
{
private:
virtual T& getValue( int index )
{
return operator[]( index );
}
public:
T& operator[]( index )
{
// find element and return it.
}
};
The idea here is that you normally only work through references
to the base class, but if performance becomes an issue, because
you're using [] in a tight loop, you can dynamic_cast to the
derived class before the loop, and use [] on the derived
class.