Why would I use a member function when I can pass a static function a reference to an object?
For example:
#include <iostream>
class Widget{
private:
int foo;
public:
Widget(){
foo = 0;
}
static void increment( Widget &w ){
w.foo++;
std::cout << w.foo << std::endl;
}
};
class Gadget{
private:
int foo;
public:
Gadget(){
foo = 0;
}
void increment(){
foo++;
std::cout << foo << std::endl;
}
};
int main(int argc, const char * argv[]){
Widget *w = new Widget();
Widget::increment( *w );
Gadget *g = new Gadget();
g->increment();
return 0;
}
Is this more than a stylistic thing? My understanding is that member functions are created per object instance, while static functions are not -- and since you can make static functions operate on a per instance basis like in the above example, shouldn't it slightly more efficient to create static functions instead of member functions?
Memeber functions are are not created by instance. They have an implicit first parameter which is the this pointer, so they actually look quite similar to your static function.
For example,
struct Foo {
void foo(int i) {}
}
Foo f;
f.foo(42);
Foo::foo(f, 42);
the two last lines do the same. However, it is hard to see how one could implement this with static methods or functions:
struct IFoo {
virtual foo() const {}
};
struct Foo1 : virtual public IFoo {
virtual foo() const {}
};
IFoo* f = new Foo1;
f->foo();
So, besides the syntactic sugar of allowing you to call the methods on an instance with the . operator, you need them for this kind of run-time polymorphism.
It's important because it allows polymorphism; specifically because it's needed for dynamic dispatch, where the method to which to bind the call is determined at runtime by the true type of the object on which it's invoked. A static call always binds to the method on the nominated type, regardless of the runtime type of the object itself.
Related
As far as I know, the member function pointer only can be assigned to the pointer to member function type, and converted to any other except this will violate the standard, right?
And when calling std::bind(&T::memberFunc, this), it should return a dependent type which depend on T.(in std of VC++ version, it's a class template called _Binder).
So the question becomes to why one std::funcion can cover all _Binder(VC++ version) types.
class A
{
public:
void func(){}
};
class B
{
public:
void func(){}
};
std::function<void(void)> f[2];
A a;
B b;
f[0] = std::bind(&A::func, &a);
f[1] = std::bind(&B::func, &b);
And I can't picture what type of the member of std::funcion which stored the function would be like, unless I am wrong from the first beginning.
This question only covered the member function need to be called with it's instance.
But mine is about why one std::function type can hold all T types.
In short what is happening is that std::bind(&A::func, &a) returns an object of a class similar to
class InternalClass
{
A* a_; // Will be initialized to &a
public:
void operator()(void)
{
a_->func();
}
};
[Note that this is highly simplified]
The callable operator() function is what is matches the void(void) signature of the std::function<void(void)>.
I think the implementation would probably like this:
template</*...*/>
class std::bind</*...*/>
{
public:
std::bind(callable_t call, param_t p)
{
_func = [call, p]()/* using lambda to capture all data for future calling */
{
p->call();
};
}
operator std::function<void(void)>()
{
return _func;
}
private:
std::function<void(void)> _func;
};
And lambda is the key.
The following code compiles and works correctly, allowing me to gain access to protected fields of a class. But is this an ok thing to do? Feel dirty, but what do i know coming from Java:
#include <iostream>
class Base {
public:
Base() : _f(42) {
}
int getF() { return _f; }
protected:
int _f;
};
class Der : public Base {
public:
void setF(int f) { _f = f; }
};
int main(int argc, char ** argv) {
Base *b = new Base();
std::cout << b->getF() << std::endl;
Der *d = reinterpret_cast<Der*>(b);
d->setF(37);
std::cout << b->getF()<< std::endl;
}
And if I am right and this is not ok, what is a good way expose internal encapsulated data fields of an object which normally don't need to be modified, but do need to be changed in testing? The instance is created deep inside other components, so changing its type is not trivial.
No, if you pretend an object is of type Der when it isn't, the behaviour is undefined. This could fail at runtime, and badly. Aside from the usual (specifically requesting your compiler to make invalid code crash), one way this could fail at runtime is if your compiler's optimiser assumes that since you are casting it to Der*, it must really be of type Der. If you then follow this by a call to a virtual function, the compiler may assume that since the dynamic type is already known as Der, virtual method lookup can be optimised away.
And if I am right and this is not ok, what is a good way expose internal encapsulated data fields of an object which normally don't need to be modified, but do need to be changed in testing?
The friend keyword seems appropriate for that. This keyword makes private (and protected) members of a class available outside of the class. Since your Base class should know which class or function will be unit-testing it, it can grant access to that class or function.
class Base {
friend class BaseTester;
// ...
protected:
int _f;
};
class BaseTester {
public:
static void test() {
Base *b = new Base();
b->_f = 37;
}
};
int main(int argc, char ** argv) {
BaseTester::test();
}
For completeness, there are a few holes in C++'s access checks that you could abuse if for some reason you cannot modify Base. Here's one:
#include <iostream>
class Base {
// ...
protected:
int _f;
};
class BaseHack : public Base {
public:
static constexpr int Base::*_f = &BaseHack::_f;
};
int main(int argc, char ** argv) {
Base *b = new Base();
b->*BaseHack::_f = 37;
}
Inside BaseHack, the expression &BaseHack::_f is allowed, because it names a protected member of a base class, accessed through its own class. But because _f is actually defined in class Base, its type is int Base::* rather than int BaseHack::*, and there is no rule preventing it from being used to access members of Base.
In class A I have a member function that should receive a pointer to functions from other classes. All those functions have the same signature (receive type and return type).
Something like this:
class A{
private:
void (*onConfirmCallback) (); //pointer to function
public:
void setOnConfirmListener(void (*callback) ()); //member function that receives another member function from another class, and uses the pointer above to point to it
}
definitions:
void A::setOnConfirmListener(void (*callback)())
{
onConfirmCallback = callback;
}
and at some point in class A I call the callback:
onConfirmCallback();
In class B I set the callback:
class B{
private:
A a;
public:
B();
foo();
}
and definitions:
B::B(){
a.setOnConfirmListener(foo);
}
B::foo(){
cout << "foo called" << endl;
}
I also have another class C which also has an instance of A, and also sets a callback:
class C{
private:
A a;
public:
C();
foo2();
}
and definitions:
C::C(){
a.setOnConfirmListener(foo2);
}
C::foo2(){
cout << "foo2 called" << endl;
}
I tried different declaration variations, and the above code generates this error:
no matching function for call to 'A::setOnConfirmListener()'
I understand that "pointers to functions" differ from "pointers to member functions". So I also tried changing void (*onConfirmCallback) () to void (B::*onConfirmCallback) () , but I don't think that's good because this pointer should hold callbacks to different classes (that don't derive from the same base class) and not only B.
Is there a way to implement this?
Basically I'm trying to do something like Java's interface...
Use std::function rather than function pointers.
class A {
private:
std::function <void()> onConfirmCallback; //pointer to function
public:
void setOnConfirmListener(std::function <void()>);
};
You can pass non-member functions directly to setOnConfirmListener. When it comes to member functions, you need an object in order to call them:
class B {
private:
A a;
public:
B();
void foo();
};
B::foo(); // invalid and makes no sense
B* b = new B; b->foo(); // OK
so the line below won't work either:
a.setOnConfirmListener(&B::foo); // invalid and makes no sense
You can pass an object together with its member function using std::bind:
a.setOnConfirmListener(std::bind(&B::foo, b)); // OK
b can be either B&, B* or std::shared_ptr<B>.
It could be a bit dangerous to use this (or *this) as the second argument for bind because you are now responsible to monitor when your object ceases to exist and unregister all its associated listeners. One way round this is to derive your objects from enable_shared_from_this and use std::shared_ptr instead of the raw this pointer. This means your object is not destroyed until it is registered as a listener in at least one callback.
An alternative is to derive all of your listeners from the same abstract base class, say Listener, and use pointers to Listener instead of function pointers.
class Listener
{
public:
virtual void callback() = 0;
};
class A {
private:
std::shared_ptr<Listener> listener; // or another smart pointer
public:
void setOnConfirmListener(std::shared_ptr<Listener> listener);
};
class B : public Listener {
private:
A a;
public:
B();
void foo();
void callback() { foo(); }
};
The downside is the necessity to derive all of your listeners from the same base class. Also, if the same class needs to have more than one listener callback, you have to jump through some hoops.
I realy don't understand why it works, but below code shows an example of calling private method from the world without any friend classes:
class A
{
public:
virtual void someMethod(){
std::cout << "A::someMethod";
}
};
class B : public A
{
private:
virtual void someMethod(){
std::cout << "B::someMethod";
}
};
int main(){
A* a = new B;
a->someMethod();
}
outputs:
B::someMethod
Doesn't it violates encapsulation rules in C++? For me this is insane. The inheritance is public, but the access modifier in derived class is changed to private, thus the someMethod() in class B is private. So in fact, doing a->someMethod(), we are directly calling a private method from the world.
Consider the following code, a modification of the code in the original question:
class A
{
public:
virtual void X(){
std::cout << "A::someMethod";
}
};
class B : public A
{
private:
virtual void Y(){
std::cout << "B::someMethod";
}
};
int main(){
A* a = new B;
a->X();
}
It's easy to understand that it's legit to call X(). B inherits it from A as a public member. Theoretically if X() would call Y() this would be legit as well of course, although this is not possible because X() is declared in A which doesn't know Y(). But actually this is the case if X = Y, i.e. if both methods have the same name.
You may think of it as "B inherits a public method from A, that calls a private method (of B) with the same name".
a is a pointer to an A object where the method is public, so this is not a violation. Since, you have used virtual, the VTABLE is taken into account and you get the output as B::someMethod.
For me this is quite simple.
As you are allowed to asign any dynamic type inheritance of a class to an object of the parrent-class it would be vise versa.But as you are assigning the Child to its parrent object pointer this could be bad as if the class of B where bigger as A.
If a program attempts to access the stored value of an object through an lvalue of other than one of the following types the behavior is undefined:
the dynamic type of the object,
a cv-qualified version of the dynamic type of the object,
a type that is the signed or unsigned type corresponding to the dynamic type of the object,
a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union),
a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
a char or unsigned char type.
So as in your code you aren't fitting this conditions, but as B has the sime size as A, it would be possible to run it. But it is undefined behavior.
And as you creat a new B the memory block a is pointing to has the method of printing B and not A.
The access control specifiers (public, protected and private) do not apply to member functions or data members. They apply to member function and data member names. And that works. If you can refer to the member without the name, you can access it.
That's precisely what's happening here. You're calling B::someMethod, but you're calling it using the name A::someMethod, which is public. No problem.
You're suggesting a private member function shouldn't be callable from outside of the class (disregarding friends for the moment). How would your desired semantics work in the following case?
Shared library hider:
hider.h:
typedef void (*FuncType)();
class Hider {
private:
static void privFunc();
public:
static void pubFunc();
FuncType getFunction() const;
};
hider.cpp
#include <cstdlib>
#include <iostream>
#include "hider.h"
void Hider::privFunc() {
std::cout << "Private\n";
}
void Hider::pubFunc() {
std::cout << "Public\n";
}
FuncType Hider::getFunction() const {
if (std::rand() % 2) {
return &pubFunc;
} else {
return &privFunc;
}
}
Application using library hider
#include "hider.hpp"
int main()
{
Hider h;
FuncType f = h.getFunc();
f();
}
What about the call to f()? Should it fail at runtime 50% of the time with some form of access control violation?
As suggested by DyP in the comments, a more realistic scenario is the well-known "template method" design pattern:
class Container
{
public:
void insert(const Item &item) {
preInsert();
data.insert(item);
postInsert();
}
private:
std::vector<Item> data;
virtual void preInsert() = 0;
virtual void postInsert() = 0;
};
class ThreadSafeContainer : public Container
{
private:
std::mutex m;
virtual void preInsert() {
m.lock();
}
virtual void postInsert() {
m.unlock();
}
};
Your semantics would mean this code wouldn't compile.
i have two classes (non-static) A & (static) B.
I am trying to store Object A into B so that i can use its functions in funcB().
However i do know that static classes cannot store non-static variables & functions. is there anyway to get pass this rather than converting Class A into a static class?
class A
{
public:
A();
void funcA();
private:
int A;
};
class B
{
public:
B(A *objA);
static void funcB();
private:
A *objA;
};
edit:
I stated static class to make it easier to explain. i did not know the correct term.
So the question is actually: How do i use a non-static member from a static function?
You can not access anything that is specific to an instance of a class from a static function by itself. A static function has no "this" pointer (the compiler passes a pointer to the instance of the object calling the function for non-static functions). You can get around this by passing a pointer to the object you want to modify, but then why are you using a static function? My advice would be to avoid what it seems like you are trying to do, but I provided 2 ways to do it below (as a good learning example).
See below for an example of using
#include <iostream>
using namespace std;
class A
{
public:
A(int value) : a(value){}
void funcA();
public:
int a;
};
class B
{
public:
B()
{
objA = new A(12);
}
void funcB2()
{
B::funcB(*objA);
}
static void funcB(A const & value)
{
cout << "Hello World! " << value.a << endl;
}
private:
A *objA;
};
int main()
{
A a(10);
B::funcB(a);
B b;
b.funcB2();
return 0;
}
I think you just should not make design like this. A static function is initialized when the non-static members are not ready. You said "the class A, links to many other classes and has stored many other information. Class B on the other hand, has to be static due to some windows API threading condition." . In this case, can you change your design and turn A into static class?