I have a base class and a derived one and I want to change base functions while keeping them static as they should be passed to other functions as static.
How can I do that?
The ATL framework gets around the limitation of no virtual statics by making the base class be a template, and then having derived classes pass their class type as a template parameter. The base class can then call derived class statics when needed, eg:
template< class DerivedType >
class Base
{
public:
static void DoSomething() { DerivedType::DoSomethingElse(); }
};
class Derived1 : public Base<Derived1>
{
public:
static void DoSomethingElse() { ... }
};
class Derived2 : public Base<Derived2>
{
public:
static void DoSomethingElse() { ... }
};
This is known as Curiously recurring template pattern, which can be used to implement static polymorphism.
Do you mean you need a pointer to a static function (e.g. to pass as an argument to another function that requires a pointer to a static function), but you need to access that function pointer virtually? In that case, use a virtual function to get the function pointer:
typedef void (*function)();
void do_stuff_with_function(function);
struct Base {
virtual ~Base() {}
virtual function get_function() = 0;
};
struct Derived : Base {
function get_function() {return my_function;}
static void my_function();
};
Derived d;
do_stuff_with_function(d.get_function());
static function can not be virtual since they do not have an instance through which they are accessed. I do believe you can overwrite them though.
You can't have static virtual functions in C++.
Virtual functions typically rely on this pointer to determine the type of function to be called at run time.
A static member function does not pass a this so static virtual functions are not allowed in C++.
If i am correct in understanding ur question, then u can follow the following approach otherwise ignore..
have static function pointer in the base class.
in base class have a static function ( in which u call the function by using that static function pointer)..
in derived classes set that static function poiter to the function defination u wish to execute.. ( in base class u can set the function pointer to some default function).
You cannot have static virtual functions, because it doesn't make sense to have them.
Related
It is very easy that we can make sure derived class must implement interface defined in base class.
That is pure virtual function.
For example:
class BaseClass
{
...
virtual void print()=0;
...
}
class DerivedClass :public BaseClass
{
// function must be implement, otherwise compiler will complain ...
void print()
{
}
};
Can we defined a static interface in base class and make sure the interface must be implement in derivate class?
I want something like this
class BaseClass
{
...
static void print(); // base class only define static interface
...
}
class DerivedClass :public BaseClass
{
// derived class must implement interface, otherwise compiler will complain ...
static void print()
{
}
};
I have no idea about this.
Thanks for your time.
It is not possible to make a virtual static function. For the simple reason that when calling a static function, you always know the class that defines that function in compile time. Unlike virtual functions, where you don't know the type of the object whose method you're calling.
For example:
class A
{
public:
virtual void f() {printf("A");}
};
class B : public A
{
virtual void f() override {printf("B");}
};
void g(A& a)
{
a.f();
}
int main()
{
B b;
g(b);
return 0;
}
In the above example, inside the function g, the correct function is invoked (B::f). Even though while compiling the function it is not known what the type of its argument is (it could be A or any class derived from A).
Without making f() virtual, you would have overloaded the method f, rather than overridden it. Which means that in the following example, the output would be "A", even though you might expect it to be "B":
class A
{
public:
void f() {printf("A");}
};
class B : public A
{
void f() {printf("B");}
};
void g(A& a)
{
a.f();
}
int main()
{
B b;
g(b);
return 0;
}
This may cause serious bugs, and it is suggested to never overload base class methods, and to always use the override keyword when overriding a virtual method to escape those bugs.
When making a static function, you can simply overload it, it would not create a compilation error. However, you probably never should overload it, because it may hide a bug that is very difficult to track (you are certain that B::f() is being called while actually A::f() is being called).
Furthermore, it is not possible to 'force' the derived class to implement a static interface, because there is no such thing as a static interface. Because you have no virtual static functions, you may not pass a reference or pointer to the interface that would implement this function.
My problem is that when I call a virtual function on an object passed to my callback function, the wrong function gets called, and I get a run-time error.
Consider the following code fragment in a header file. The code may not compile as it is only a fragment.
class CEventBase1{
protected:
virtual void Show(int code){}
private:
static void _Base1Callback(void*ptr){
CEventBase1* pThis = static_cast<CEventBase1*>(ptr);
pThis->Show(EVENT_CODE);
}
};
class CEventBase2{
protected:
virtual void Move(int code){}
private:
static void _Base2Callback(void*ptr){
CEventBase2* pThis = static_cast<CEventBase2*>(ptr);
pThis-> Move(EVENT_MOVE);
}
};
class CAllEvents: public CEventBase1, public CEventBase2{
};
template<typename EVENTS>
class CWindow : public EVENTS{
};
class CMyEvents: public CAllEvents{
public:
virtual void Move(int code){
// Some processing
}
};
CWindow<CMyEvents> myWin;
This code will interact with some library in which the window instance is registered to handle events. Something similar to:
int main () {
SomeLibraryRegisterCallbackData(&myWin);
SomeLibraryRegisterEvent1Callback(CEventBase1::_Base1Callback);
SomeLibraryRegisterEvent2Callback(CEventBase2::_Base2Callback);
return SomeLibraryDispatch();
}
The idea is that during the dispatch, the pointer to myWin gets passed to a registered callback whenever the event it is registered against occurs.
Problem: When the program tries to call the CMyEvents::Move() from the static function _Base2Callback(), the CEventBase1::Show() function gets called and the program crashes in the caller function as soon as Show() returns with the error:
ESP pointer is of incorrect type. this may happen when an incorrect method is called
Compiler: Visual C++ 2012.
Since you are passing in a pointer to a CWindow<CMyEvents> instance to CEventBase2::_Base2Callback, then the static cast of the void * argument to CEventBase2 * is in error. Although there is an is-a relationship between the two, it is through multiple inheritance. In practical terms, this means that the object layout is such that for an instance of CMyEvents, its address is not the same as the address of the CEventBase2 instance from which it is derived.
The straightforward way to avoid this problem is to avoid using void * altogether. However, since you are using a library, then you must make your code compatible with the framework. In your case, you want each base class to define its own callback function. This means that the base class needs to be aware of the derived type, because it is the pointer to the derived type that is being passed into the callback function.
This can be accomplished using CRTP. Make each base class a template class that is parameterized by its derived class. Then, the callback function can cast to the derived type:
template <typename DERIVED>
class CEventBase1{
protected:
virtual void Show(int code){}
protected:
static void _Base1Callback(void*ptr){
DERIVED* pThis = static_cast<DERIVED*>(ptr);
pThis->Show(EVENT_CODE);
}
};
template <typename DERIVED>
class CEventBase2{
protected:
virtual void Move(int code){}
private:
static void _Base2Callback(void*ptr){
DERIVED* pThis = static_cast<DERIVED*>(ptr);
pThis-> Move(EVENT_MOVE);
}
};
You would also make CAllEvents a template class as well, so it can properly pass the right derived type to the base classes:
template <typename DERIVED>
class CAllEvents: public CEventBase1<DERIVED>, public CEventBase2<DERIVED>{
};
And now, the user of the of that class uses it like this:
class CMyEvents: public CAllEvents<CMyEvents>{
public:
void Move(int code){
// Some processing
}
};
Because of the way CWindow<> is defined, the address of an instance of it would be the same as the address of the CMyEvents instance from which it is derived. The callback functions in the base classes will cast the pointer to a CMyEvents*.
#include <memory>
class Base
{
std::shared_ptr<Base> create() const; // Returns a default constructed object
}
Suppose, that all the members derived to whatever degree from Base are copy constructible and default constructible. I want the
std::shared_ptr<Base> create() const;
Method to create object of the appropriate dynamic type, but I do not want to use boilerplate code.
Is it possible to make
std::shared_ptr<Base> create() const;
Statically bound, but inside find somehow the correct type and create the object using Default constructor? Possibly using C++11.
The create() functions should probably be static, as you don't have an instance yet. But without parameters you cannot do what you want... unless you use templates, of course:
class Base
{
public:
template<typename T>
static std::shared_ptr<Base> create() const
{
return std::shared<Base>(new T);
}
};
Then use it this way:
std::shared_ptr<Base> ptr(Base::create<Foo>());
Or, if you prefer:
std::shared_ptr<Base> ptr(Foo::create<Foo>());
Ideally you have a static and perhaps a non-static create() functions. There is a clever way to accomplish this.
Define a SuperBase class. It needs a virtual destructor and a pure virtual create() function. You'll use pointers/references to this class for normal late-binding OOP behaviours.
Define a Base class template that inherits from SuperBase. Base's template parameter will be the type of the Derived class. Base will also have a traits class template with a static function called create(). This static create() function will create a default object with new. Using the trait's create() function, Base will define both a static_create() and the pure virtual SuperBase::create() functions.
Implement Derived by inheriting from Base<Derived>.
One this is done, if you know you are using a derived type, then you can write Derived::create() to statically create a new one. If not, then you can always use an instance's create() method. Polymorphism is not broken since SuperBase would have the polymorphic interface you need/want --Base<D> is simply a helper class that auto defines the static_create() and create() functions so you would not normally use Base<D> directly.
Sample code appears below:
#include <memory>
#include <iostream>
class SuperBase
{
public:
virtual ~SuperBase() = default;
virtual std::shared_ptr<SuperBase> create() const = 0;
};
template <typename T>
struct Base_Traits
{
static T* create()
{
return new T;
}
};
template <typename Derived, typename Traits=Base_Traits<Derived>>
class Base : public SuperBase
{
public:
// Define a static factory function...
static std::shared_ptr<SuperBase> static_create()
{
return std::shared_ptr<SuperBase>{Traits::create()};
}
// Define pure virtual implementation...
std::shared_ptr<SuperBase> create() const override
{
return static_create();
}
};
class Derived : public Base<Derived>
{
};
int main()
{
auto newone = Derived::static_create(); // Type known # compile time
auto anotherone = newone->create(); // Late binding; type not known # compile time
}
What is the advantage of defining static methods with exact same signature as the interface method in the class which implements it .
class IInterface
{
public:
virtual void fn()=0;
}
class Impl :IInterface
{
public:
~Impl();
static void fn();
}
Impl::~Impl{
}
Impl::fn(){
//do something
}
There is no advantage of having such static method. static methods don't override virtual methods (which are always non-static).
In fact it has disadvantage, that you cannot implement the actual method to override the base method. Because one cannot have same method signature in a single class (one static and another non-static).
class Impl :IInterface
{
public :
~Impl();
staic void fn();
void fn() {} // error: invalid (can't have same signature)
};
There is no advantage.
Your derived class Impl still is as an Abstract class since it does'nt & can't override the pure virtual function. You cannot create any objects of it.
A static function cannot override a virtual function from Base class because dynamic polymorphism uses the this to evaluate the function call at run time, while static functions do not pass the this pointer, because they are not specific to any object.
class Base{
public:
void counter();
....
}
class Dervied: public Base{
public:
....
}
void main()
{
Base *ptr=new Derived;
ptr->counter();
}
To identify that the base class pointer is pointing to derived class and using a derived member function, we make use of "virtual".
Similarly, can we make derived data members "virtual"? (the data member is public)
virtual is a Function specifier...
From standard docs,
7.1.2 Function specifiers
Function-specifiers can be used only in function declarations.
function-specifier:
inline
virtual
explicit
So there is nothing called Virtual data member.
Hope it helps...
No, but you can create a virtual function to return a pointer to what you call virtual data member
No, in C++ there are no virtual data members.
I think not, but you might simulate it using virtual getters and setter perhaps?
To identify that the base class pointer is pointing to derived class and using a derived member function, we make use of "virtual".
That is not correct. We make virtual functions to allow derived classes to provide different implementation from what the base provides. It is not used to identify that the base class pointer is pointing to derived class.
Similarly, can we make derived data members "virtual"? (the data member is public)
Only non static member functions can be virtual. Data members can not be.
Here's a link with some more info on that
No, because that would break encapsulation in a myriad of unexpected ways. Whatever you want to achieve can be done with protected attributes and/or virtual functions.
Besides, virtual functions are a method of dispatch (i.e. selecting which function is going to be called), rather than selecting a memory location corresponding to the member attribute.
A class cannot have a virtual member, see for instance this answer.
However, you can have something similar using pointers, inheritance
and runtime polymorphism.
In the following snippet I define the prototype for a geometrical shape,
that has an area method. The picture class has a member shape* s;
and the methods of that shape pointed by s are used by picture::show().
In this setup it is undesirable to have an instance of picture before
an actual implementation of a shape has been given, hence we force picture to be
abstract by adding a dummy virtual function picture::make_real().
// prototypes
class shape
{
public:
virtual double area() = 0; // to be defined later
};
class picture
{
protected:
shape* s;
virtual void make_real() = 0; // force picture to be abstract
public:
picture(shape* ptr):
s{ptr}
{}
void show()
{
std::cout << s->area() << '\n';
}
};
Next, we actually implement a shape called square and a picture type
square_picture that (literally) has a square shape.
// actual implementation
class square : public shape
{
double len;
public:
square(double l):
len{l}
{}
double area() override
{
return len*len;
}
};
class square_picture : public picture
{
void make_real() override {} // square_picture is not abstract
public:
square_picture(double l):
picture{new square{l}}
{}
~square_picture()
{
delete s;
}
};
The class square_picture can be tested with the following snippet
int main()
{
square_picture A{2.0};
A.show();
//picture B{nullptr}; // error: picture is abstract
return 0;
}
which outputs:
4
I have a base class which uses an array of objects. From that class I derived a new class that uses an array of a different type of object. Both variables have exactly the same name. Virtual member functions were added to both classes to process the arrays. These member functions have no trouble finding the correct variable. The member functions and the variables they use are in a common scope.
The virtual member functions are nearly identical in both classes. Only the type of array changed.
C++ templates could have accomplished the same result.
Maybe you can see the problem in a equivalent way:
class VirtualDataMember{
public:
...
}
class DerviedDataMember: public VirtualDataMember{
public:
...
}
class Base{
public:
VirtualDataMember* dataMember;
void counter();
...
}