When using encapsulation and "tell, don't ask"-principle properly, there should be no reason for one to ask information from an object.
However, I've ran into a situation (let me know if this design itself is terrible) where I have an object with a member variable pointing to a function outside of the class.
At some point of my application, there's a need for my object to call the function and the function should then act based on my object's status.
Here's an example class:
typedef void(*fptr)(Foo*);
class Foo {
public:
Foo(string name, fptr function);
void activate()
{
m_function(this);
}
private:
string m_name;
fptr m_function;
};
That's the class, now the developer can use the class like so;
void print(Foo *sender)
{
cout << "Print works!" << endl;
}
int main(int argc, char **argv)
{
Foo foo("My foo", &print);
foo.activate();
// output: "Print works!"
}
This all works fine, but what if I want to print the name of the sender?
All the functions are defined outside of the class, by other developers, so there's no way to access private variables.
In C#, you can just use the partial keyword to add a method to an existing class.
This is not possible in C++ though.
I could just ignore encapsulation and create a setter and getter for name and all other properties that might be needed by the function in the future.
This is pretty terrible solution, I should basically create setter and getter for everything there is in my class, since the function can do anything to my object.
Besides what's the reason of encapsulation, if I'm just gonna ignore it when I want to?
An other solution would be a struct that holds the required properties inside it:
struct FooBar {
string name;
};
typedef void(*fptr)(FooBar);
void Foo::activate()
{
FooBar fb;
fb.name = m_name;
m_function(fb);
}
But this is not much different from not using encapsulation, and it doesn't seem like a too good solution either.
What would be the best approach for this problem?
I would make activate() an abstract method and all the class' properties protected.
Also, there's no need for the fptr:
class Foo {
public:
Foo(string name);
virtual void activate() = 0;
protected:
string m_name;
};
Now when someone wants to use your class, he just inherits his own from it:
class MyFoo : public Foo {
public:
MyFoo(string name);
virtual void activate()
{
cout << m_name << " says: Hello World!" << endl;
}
};
int main(int argc, char **argv)
{
MyFoo foo("My foo");
foo.activate();
// output: "My Foo says: Hello World!"
}
And if you need many different Foo's with different functionality, just inherit multiple classes instead of declaring multiple functions.
Edit: Instead of inheriting a new class for every different Foo instance, you could inherit one class for all of them with all the different methods.
Now all left for activate is to decide which method to call; use enum for this:
enum MyFooFunction {
printName,
printHello
};
class MyFoo : public Foo {
public:
MyFoo(string name, MyFooFunction function);
void printName() { cout << m_name << endl; }
void printHello() { cout << "Hello!" << endl; }
virtual void activate()
{
switch(m_function) {
case printName:
printName();
break;
case printHello:
printHello();
break;
}
}
protected:
MyFooFunction m_function;
};
Seen from the outside, private variables don't exist, so developers cannot possibly "want" to print them.
If they do want then either the class members (or better, queries in the class returning their contents) should be public, the function a member of the class, or in specific cases some friend mechanism may be used.
To summarize, don't set out to break encapsulation - instead, reconsider the abstraction behind your encapsulation and, if needed, create new queries for properties of your class which weren't foreseen as useful back when the class was designed - but now are.
You might want to change your function parameter type to const string & if the function should be able to see the string, but the rest of the outside world shall not see it. Also you might consider to use std::function<void(const string &)> instead of your function type. This has two fundamental advantages: You can pass closures (also called lambdas) to your constructor and you can read it more easily. The edited code would look like this:
class Foo {
public:
template <typename F>
Foo(string name, F && function)
: m_name (std::move(name))
, m_function(std::forward<F>(function))
{
}
void activate()
{
m_function(m_name);
}
private:
string m_name;
std::function<void(const string &)> m_function;
};
The client code would look like
int main(int argc, char **argv)
{
Foo foo("My foo", [](const string & s){ cout << s << endl; });
foo.activate();
// output: "My foo"
}
You see that the client does not need to define an extra function, but can simply do it 'inline'.
What you're asking is "How can I keep my members private, but still give callbacks some way of accessing them?"
When you look at it that way, your struct FooBar solution is actually pretty reasonable. The only problem is that it's a bit inefficient. You would be better off passing a const FooBar& instead of passing FooBar by value.
Your struct FooBar solution is even better than partial classes, because you can specify exactly which members the callback should have access to.
Edit: Reading your struct FooBar solution more closely, I see you're thinking of tediously copying the members individually before passing them to the callback. You can skip all that just by putting a FooBar object in your Foo class, like so:
struct FooBar {
string name;
};
typedef void(*fptr)(const FooBar&);
class Foo {
public:
Foo(string name, fptr function);
void activate()
{
m_function(data);
}
private:
FooBar data;
fptr m_function;
};
It's worth pointing out that, with this solution, the callbacks cannot access m_function, unless you decide to put it in FooBar. This is what I meant when I said that you can specify exactly which members the callback should have access to.
Let's face it, C++ access control was designed with some use cases in mind, and are generally usable, but never claimed to cover everything. If you can't solve the situation with just private and friend, and arbitrary functions must be allowed to access the internals, then best way is to make them public and move on.
Setters will not move you forward for sure, just add complexity for nothing. If data is effective public don't try to mask that fact pretending like it wasn't.
Look for the root cause -- why on earth outsides want your members and rearrange that.
I could just ignore encapsulation and create a setter and getter for name and all other properties that might be needed by the function in the future. This is pretty terrible solution, I should basically create setter and getter for everything there is in my class, since the function can do anything to my object.
True - this is basically making implementation details public (and in most cases, not something you should do).
An other solution would be a struct that holds the required properties inside it:
[...] But this is not much different from not using encapsulation, and it doesn't seem like a too good solution either. What would be the best approach for this problem?
Actually it is very different. Consider that you are actually calling an external function with normal parameters:
struct EventData { string name, yadayada; }
class Foo
{
public:
void activate()
{
m_function( EventData(m_name, yadayada) );
}
};
This is not accessing private data (Foo accesses it's own private data, m_function accesses it's own parameter values), but dependency injection.
There are no architecture compromises with this approach.
Related
I'm NOT talking about typeid, I'm just looking for general method to bind a single object (e.g. std::string like in my case) to objects of some class and make its getter polymorphic or something. I can't really give a proper definition so i think that it's just like the problem of getting a class name but you set it yourself somewhere and the only problems are where do you set it and how do you return it.
I'm just gonna give a few examples that do what I want but aren't really as efficient as I want them to be.
virtual string GetClassName() const { return string("MyClass"); } - consumes extra time to build and copy a string every time it is called
const string& GetClassName() const { return class_name_; } where class_name_ is a protected class field that is set in the constructor - the same string is stored in every object, thus it is not memory-efficient
I'm thinking about something like returning a const reference to a static object, but I can't really find a way to make it polymorphic.
Any ideas?
You don't need to reinvent the wheel, when you can just extend it with the right tire.
The C++standard gives you typeid() that works in all the the cases, including built-in types, custom classes, polymorphic classes, multiple inheritance, virtual inheritance and things like that.
Now you may not like the names used by typeid(), which are implementation specific. Or you may want to extend the information available with your own type management extensions. In this case, Bjarne Stroustrup proposed in "The design and evolution of C++" a very simple and effective solution.
The typeid() returns a reference to a const std::type_info. Now you can use the address of this object in a unordered_map, to map the type to your own custom information that could provide the name you want.
The advantage of this solution: uses robust built-in capability, is based on a single additional object per class (could be static), very low overhead to get to the name. all you need to do is to think about how to best populate the map.
Here a small and quick proof of concept (must be improved of course):
// Basic principle of the idea
map<const type_info*, string> mytypes;
template <class T>
const string& mytype(T &&x) {
return mytypes[&typeid(x)];
}
// Some test types
struct A { virtual int test() {} };
struct B : A {};
int main() {
// To be improved: initialization of the type info extension
mytypes[&typeid(int)]="Plain C++ integer";
mytypes[&typeid(A)]="Structure A";
mytypes[&typeid(B)]="Structure B";
// demo, including polymorphic type
int a;
A * p = new B;
cout << typeid(int).name() <<endl;
cout << mytype(a) <<endl;
cout << mytype(*p) <<endl;
return 0;
}
Online demo
What I think you want is some base NamedClass with a virtual std::string_view getName() const that returns the name of the derived class. So you want something like typeid(object).name() but without the name mangling.
Every class that derives from NamedClass should override getName and return the class name.
class NamedClass {
public:
virtual std::string_view getName() const = 0;
};
class Derived final : public NamedClass {
public:
std::string_view getName() const override {
return "Derived";
}
};
If you hate this duplication as much as I do, you could use a macro.
#define GET_NAME(NAME) \
std::string_view getName() const override { return #NAME; }
class Derived final : public NamedClass {
public:
GET_NAME(Derived)
};
I highly recommend using a std::string_view instead of a const std::string & if all you want to do is "view" the string.
I have a collection of objects that implement an interface, and I want to have getters on it to get the individual implementations only in C++. In Java, I would do this:
interface IFooBar { }
class Foo implements IFooBar { }
class Bar implements IFooBar { }
class Container extends HashSet<IFooBar> {
public Container() { }
public Container(Collection<? extends IFooBar> c) { super(c); }
Foo getFoo() {
return getFoos().iterator().next();
}
Set<Foo> getFoos() {
HashSet<Foo> result = new HashSet<>();
for(IFooBar item:this) if (item instanceof Foo) result.add((Foo) item);
return result;
}
Bar getBar() { /* ... same ... */ }
Set<Bar> getBars() { /* ... same ... */ }
}
Now I tried to do the same in C++. For project requirement, I have to use shared_ptr<> of my objects. This is how far I came:
class IFooBar { }
class CFoo : IFooBar { }
class CBar : IFooBar { }
class CContainer {
public:
CContainer();
CContainer(std::vector<const std::shared_ptr<IFooBar>> cPrivData);
const std::shared_ptr<CFoo> CFoo();
std::vector<const std::shared_ptr<CFoo>> CFoos();
/* ^^^^ : Function CContainer::CFoo is not a type name */
const std::shared_ptr<CBar> CBar();
std::vector<const std::shared_ptr<CBar>> CBars();
private:
std::vector<const std::shared_ptr<IObject>> m_cPrivData;
};
Obviously this does not work, I cannot give the getter the name it should have (as I think). I get the indicated error. The function seems to undefine the type name. Now I wonder which would be an intuitively usable implementation of what I gave als Java example in C++? Or, what would be the recommended name for the getter? I learned that in C++ the getter is named without leading ‘get’, and function names start uppercase. I want the getter to reflect what class type it returns.
Perhaps I should go a completely other way? Instead of function CFoo(), could I define an assignment constructor, if so, how? Do I have to overload shared_ptr<> to do so? If so, how? Something like this was my idea:
class CSharedFooBarPointer : std::shared_pointer<IFooBar> {
public:
shared_ptr<Foo> operator=(std::vector<const std::shared_ptr<IFooBar>>& cContainer);
shared_ptr<Bar> operator=(std::vector<const std::shared_ptr<IFooBar>>& cContainer);
}
(Maybe I think too Java’ish here, but I am quite new to C++.) Perhaps this approach is bad because maybe I cannot use it in-line. Or can I? From the Java example above, I want to be able to do things like container.getFoo().doSomethingFooSpecific();. In C++, what would I have to use for syntax? Is there something like ((CFoo)cContainer).DoSomethingFooSpecific();? I don’t want to need to assign a variable if I only use it once, if possible.
Note: the code in this answer is untested and may contain typos.
I learned that in C++ the getter is named without leading ‘get’, and function names start uppercase.
Not to my knowledge. But as mentioned by Gill Bates, C++ doesn't have a centralized style guide, so just pick a code style and stick to it. I personally never see functions starting with capitals outside of ol' MFC and WINAPI -- you might be thinking of C# on that one. Ditto for the C class prefix.
In any case, name collisions can be resolved with the scope resolution operator :::
class CContainer {
// ...
const std::shared_ptr<CFoo> CFoo();
std::vector<const std::shared_ptr<::CFoo>> CFoos();
// CFoo from the global scope ^^
// ...
};
Getting one step ahead about implementing the functions:
To determine the dynamic type of an object at runtime, you need dynamic_cast, or in your case the std::dynamic_pointer_cast helper function.
std::vector<const std::shared_ptr<::CFoo>> CContainer::CFoos() {
std::vector<const std::shared_ptr<::CFoo>> result;
for(auto const &objPtr : m_cPrivData)
if(auto fooPtr = std::dynamic_pointer_cast<::CFoo>(objPtr))
result.push_back(std::move(fooPtr));
return result;
}
However, dynamic_cast requires the object's type to be polymorphic, which means that IFooBar needs to have at least one virtual member function. If no adequate function is present, a common choice is to make the destructor virtual:
struct IFooBar {
virtual ~IFooBar() = default;
};
Note on efficiency:
Just like instanceof in Java, dynamic_cast is a pretty expensive operation. If the main use case of this class is to filter that list of CFoos and CBars, you probably want to do this once in the constructor, and store them in separate containers:
class CContainer {
public:
CContainer(std::vector<const std::shared_ptr<IFooBar>> cPrivData) {
for(auto const &objPtr : cPrivData)
if(auto fooPtr = std::dynamic_pointer_cast<::CFoo>(objPtr))
_foos.push_back(std::move(fooPtr));
else if(auto barPtr = std::dynamic_pointer_cast<::CBar>(objPtr))
_bars.push_back(std::move(barPtr));
}
private:
std::vector<const std::shared_ptr<::CFoo>> _foos;
std::vector<const std::shared_ptr<::CBar>> _bars;
};
I want to achieve the "this line" in the following code. The most logical way is to set GetDog static, but then I cannot use "this". Is there a way to get around it? (not, since I was trying it out, there several lines not relevant to the question)
#include <iostream>
class Dog
{
public:
static int a;
Dog& GetDog(int k)
{
this->a = k;
return *this;
}
int bark()
{
return a*a;
}
};
int Dog::a=0;
int main()
{
Dog puppy;
int i = puppy.GetDog(4).bark();
cout<<i<<endl;
cout<<Dog::a<<endl;
//i = Dog::GetDog(6).bark(); //this line
return 0;
}
Not that doing this has much advantage (just that declaring a class is not required), but i saw it's used in some package I am using. I kind of want to understand how it is done.
class EXOFastFourierTransformFFTW
{
public:
static EXOFastFourierTransformFFTW& GetFFT(size_t length);
virtual void PerformFFT(const EXODoubleWaveform& aWaveform, EXOWaveformFT& aWaveformFT);
...
int main()
{
EXODoubleWaveform doublewf;
EXOWaveformFT wfFT;
...
EXOFastFourierTransformFFTW::GetFFT(doublewf.GetLength()).PerformFFT(doublewf,wfFT);
...
This static function usage also appears in Geant4, which probably is written by physicists, and so they might not do the wisest thing in programming. I still want to want if doing so has other advantages though.
From the vote down before I can see that this probably is not a regular method as I thought it is. Please comment so before doing it.
It seems that it is an implementation of the Meyers singleton.
I explain :
In the example given, the class EXOFastFourierTransformFFTW does not seem to have a constructor but return a reference to a EXOFastFourierTransformFFTW object.
And it looks like this implementation :
class Singleton
{
public:
static Singleton& Instance()
{
static Singleton obj;
return obj;
}
private:
Singleton();
};
From this book from Andrei Alexandrescu, it is said :
This simple and elegant implementation was first published by Scott Meyers; therefore, we'll refer to it as the Meyers Singleton.
The Meyers singleton relies on some compiler magic. A function-static object is initialized when the control flow is first passing its definition. Don't confuse static variables that are initialized at runtime[...]
[...]
In addition, the compiler generates code so that after initialization, the runtime support registers the variable for destruction.
So it good to use static to call a method from a class not instantiated but don't do it if it is not necessary... Here to represent a Singleton Pattern you have to.
But now if you want your class Dog look like that :
class Dog
{
public:
static Dog& GetDog(int k)
{
static Dog obj( k );
return obj;
}
int bark()
{
return a*a;
}
private:
int a;
Dog( int iA ) : a( iA ) {}
};
The static function usage is correct - it lets you use functions from classes without having an instance of the class. The FFT example you gave probably creates an instance within the static function. So in your case, you would instantiate Dog within the GetDog function (just be careful with returning references to local variables!).
You say that you can't use this if you make it static, which is true. But why would you want to access it without using an Object instance if you're going to need to use this at some point in the future? If it has a default value, or something like that, you could declare that elsewhere outside of the function as public static and then access it that way. If you clarify a little bit more as to what you're doing, I'll edit/remove this answer accordingly.
I need to provide a certain operation on the elements of my class Foo. This operation is specific and weird enough that I don't really want to make it a member function. On the other hand, it works on the internals of the class, which I don't want to expose.
Here is the class:
class Foo {
typedef std::map<int,double> VecElem;
std::vector<VecElem> vec_;
public:
void Insert(std::size_t index0, int index1, double d);
// ... other essential functions
};
void Foo::Insert(std::size_t index0, int index1, double d) {
vec_[index0][index1] = d;
}
The operation I need to support is to map the index1 of each element inserted so far to a new index, according to a given old-to-new index map:
void MapIndex1(const std::map<std::size_t,std::size_t>& old_to_new);
Given how Foo currently stores its elements this means a complete restructuring of the internal data, but this should not be exposed to the user. But also it shouldn't be a member function.
Is this a typical case of a friend non-member function? Are there any other possibilities? I don't really like the concept of a friend non-member function, because this weird function (which might be only temporarily necessary as a workaround for some problem) will still need to be mentioned inside the "official" class body (which is supposed to never change). But I guess I can't get around that?
What about a public nested class to do the work? Then it could have a MapIndex1 function that automatically gains access to the private members of its enclosing class. When you're done, just remove the nested class.
class Foo {
// ...
public:
void Insert(std::size_t index0, int index1, double d);
// ... other essential functions
class Remapper
{
public:
Remapper(Foo& foo) : foo_(foo) { }
void MapIndex1(const std::map<std::size_t,std::size_t>& old_to_new);
private:
Foo& foo_;
};
};
Foo myFoo;
Foo::Remapper remapper(myFoo);
remapper.MapIndex1(...);
An idea for dealing with this scenario is to add a function like:
void Ioctl(int func, void* params); to your class. This function can then be used as a gateways for all of these hackey temporary scenarios as they arise. They can then be safely removed when the requirement disappears without breaking compatibility (unless of course someone unofficially uses them).
True you do lose type safety but it does provide a nice swiss army knife approach for all such problems.
Internally you can define certain integer func values to call a function and cast the params value to whatever you need.
I want to implement a class in c++ that has a callback.
So I think I need a method that has 2 arguments:
the target object. (let's say
*myObj)
the pointer to a member function of
the target object. (so i can do
*myObj->memberFunc(); )
The conditions are:
myObj can be from any class.
the member function that is gonna be the callback function is non-static.
I've been reading about this but it seems like I need to know the class of myObj before hand. But I am not sure how to do it. How can I handle this? Is this possible in C++?
This is something I have in mind but is surely incorrect.
class MyClassWithCallback{
public
void *targetObj;
void (*callback)(int number);
void setCallback(void *myObj, void(*callbackPtr)(int number)){
targetObj = myObj;
callback = callbackPtr;
};
void callCallback(int a){
(myObj)->ptr(a);
};
};
class Target{
public
int res;
void doSomething(int a){//so something here. This is gonna be the callback function};
};
int main(){
Target myTarget;
MyClassWithCallback myCaller;
myCaller.setCallback((void *)&myTarget, &doSomething);
}
I appreciate any help.
Thank you.
UPDATE
Most of you said Observing and Delegation, well that's i exactly what i am looking for, I am kind of a Objective-C/Cocoa minded guy.
My current implementation is using interfaces with virtual functions. Is just I thought it would be "smarter" to just pass the object and a member function pointer (like boost!) instead of defining an Interface. But It seems that everybody agrees that Interfaces are the easiest way right? Boost seems to be a good idea, (assuming is installed)
The best solution, use boost::function with boost::bind, or if your compiler supports tr1/c++0x use std::tr1::function and std::tr1::bind.
So it becomes as simple as:
boost::function<void()> callback;
Target myTarget;
callback=boost::bind(&Target::doSomething,&myTarget);
callback(); // calls the function
And your set callback becomes:
class MyClassWithCallback{
public:
void setCallback(boost::function<void()> const &cb)
{
callback_ = cb;
}
void call_it() { callback_(); }
private:
boost::function<void()> callback_;
};
Otherwise you need to implement some abstract class
struct callback {
virtual void call() = 0;
virtual ~callback() {}
};
struct TargetCallback {
virtual void call() { ((*self).*member)()); }
void (Target::*member)();
Target *self;
TargetCallback(void (Target::*m)(),Target *p) :
member(m),
self(p)
{}
};
And then use:
myCaller.setCallback(new TargetCallback(&Target::doSomething,&myTarget));
When your class get modified into:
class MyClassWithCallback{
public:
void setCallback(callback *cb)
{
callback_.reset(cb);
}
void call_it() { callback_->call(); }
private:
std::auto_ptr<callback> callback_;
};
And of course if the function you want to call does not change you may just implement some interface, i.e. derive Target from some abstract class with this call.
One trick is to use interfaces instead, that way you don't need specifically to know the class in your 'MyClassWithCallback', if the object passed in implements the interface.
e.g. (pseudo code)
struct myinterface
{
void doSomething()=0;
};
class Target : public myinterface { ..implement doSomething... };
and
myinterface *targetObj;
void setCallback(myinterface *myObj){
targetObj = myObj;
};
doing the callback
targetObj->doSomething();
setting it up:
Target myTarget;
MyClassWithCallback myCaller;
myCaller.setCallback(myTarget);
The Observer design pattern seems to be what you're looking for.
You have a few basic options:
1) Specify what class the callback is going to use, so that the object pointer and member function pointer types are known, and can be used in the caller. The class might have several member functions with the same signature, which you can choose between, but your options are quite limited.
One thing that you've done wrong in your code is that member function pointers and free function pointers in C++ are not the same, and are not compatible types. Your callback registration function takes a function pointer, but you're trying to pass it a member function pointer. Not allowed. Furthermore, the type of the "this" object is part of the type of a member function pointer, so there's no such thing in C++ as "a pointer to any member function which takes an integer and returns void". It has to be, "a pointer to any member function of Target which takes an integer and returns void". Hence the limited options.
2) Define a pure virtual function in an interface class. Any class which wants to receive the callback therefore can inherit from the interface class. Thanks to multiple inheritance, this doesn't interfere with the rest of your class hierarchy. This is almost exactly the same as defining an Interface in Java.
3) Use a non-member function for the callback. The for each class which wants to use it, you write a little stub free function which takes the object pointer and calls the right member function on it. So in your case you'd have:
dosomething_stub(void *obj, int a) {
((Target *)obj)->doSomething(a);
}
4) Use templates:
template<typename CB> class MyClassWithCallback {
CB *callback;
public:
void setCallback(CB &cb) { callback = &cb; }
void callCallback(int a) {
callback(a);
}
};
class Target {
void operator()(int a) { /* do something; */ }
};
int main() {
Target t;
MyClassWithCallback<T> caller;
caller.setCallback(t);
}
Whether you can use templates depends whether your ClassWithCallback is part of some big old framework - if so then it might not be possible (to be precise: might require some more tricks, such as a template class which inherits from a non-template class having a virtual member function), because you can't necessarily instantiate the entire framework once for each callback recipient.
Also, look at the Observer Pattern and signals and slots . This extends to multiple subscribers.
In C++, pointers to class methods are hardly used. The fact that you called in - it is delegates and their use is not recommended. Instead of them, you must use virtual functions and abstract classes.
However, C++ would not have been so fond of me, if it not supported completely different concepts of programming. If you still want delegates, you should look towards "boost functional" (part of C + +0 x), it allows pointers to methods of classes regardless of the class name. Besides, in C++ Builder has type __closure - implementation of a delegate at the level of the compiler.
P.S. Sorry for bad English...