Suppose there are two classes Foo and Bar, with Bar depending on some state provided by Foo. These classes may have a structure as follows:
class Foo
{
public:
// Constructors and destructors
const State& get_state() const;
/* Invalidates and recreates the 'State' object passed by 'get_state' */
void handle_event();
private:
// private member variables
};
class Bar
{
public:
Bar(const Foo& foo);
private:
const State& m_state; //Assigned via foo.get_state()
};
Assuming that besides combining both Foo and Bar into a single class, this the way the State must be passed. Furthermore assume that there can be multiple Bar classes using the State from Foo.
When the handle_event member function is called what is the pattern or "standard" way of handling the situation such that Bar is always in a valid state?
I can imagine that something like Bar registering itself with Foo during its construction can provide such a mechanism. An example of this is below. The issue with this is I feel it may be too tightly coupled.
class Foo
{
public:
void register_dependency(Bar* bar);
void deregister_dependency(Bar* bar);
private:
std::set<Bar *> m_dependencies;
};
class Bar
{
public:
void invalidate_state(const Foo& foo);
};
I would go with a system like the one you have proposed. It is a version of the well-established observer pattern.
If you think other types besides Bar might need state from Foo, then you could use an interface to decouple.
class Foo;
class IFooStateObserver {
public:
virtual ~IFooStateObserver() {}
virtual void invalidate_state(const Foo& foo) = 0;
};
class Foo {
public:
void register_dependency(IFooStateObserver* observer);
void deregister_dependency(IFooStateObserver* observer);
private:
std::set<IFooStateObserver*> m_dependencies;
};
class Bar : public IFooStateObserver {
public:
void invalidate_state(const Foo& foo) override;
};
A similar system could isolate Foo from Bar if necessary.
Related
Say we have a class that has a private constructor, through friend we can allow some specific class(es) to still create objects of this class:
class Foo
{
friend class Bar;
private:
Foo();
};
class Bar
{
Bar()
{
//create a Foo object
}
};
Now what if I want the opposite of friend, where Foo looks like this:
class Foo
{
//enemy/foe??? class Bar; (if only)
public:
Foo();
};
And then no method of Bar can access the Foo constructor/ make an object of Foo but other classes can (because it's public).
class Bar
{
Bar()
{
Foo foo; //compiler error
}
};
Is such a construct possible or am I stuck with keeping Foo private and adding friends for all the classes?
Such a thing does not exist, and it would be extremely pointless. Imagine you have a situation like this:
class Foo
{
enemy class Bar;
public:
Foo() {}
};
class Bar
{
void evil() { Foo{}; }
};
Nothing prevents the implementor of Bar from doing this:
class Bar
{
void evil() { do_evil(*this); }
};
void do_evil(Bar &self)
{
Foo{};
}
do_evil is not a member of Bar (it's a global function), and so it's not an enemy. Such non-friendliness could therefore be trivially circumvented.
It cannot be done really, but maybe following is enough for you:
template <typename T> struct Tag {};
class Foo
{
public:
template <typename T>
Foo(Tag<T>) {}
Foo(Tag<Bar>) = delete;
// ...
};
And so asking "creator" to "identify" itself.
class Bar
{
Bar()
{
Foo foo{Tag<Bar>{}}; //compiler error
// Foo foo{Tag<void>{}}; // valid as we can cheat about identity.
}
};
There is no such concept in C++.
Public attributes will always be public, but you can limit the exposure of Foo by making the constructor protected, for instance, and only visible for selected classes (although limiting friend is advised). Perhaps also make Foo as a protected class of Bar2 because only Bar2 or its children will actually use it.
As it has already been sayed by others, your desire breaks the idea of encapsulation because you cannot always know who your enemies are.
But, still, there is a possibility to get (almost) what you want:
#include <type_traits>
struct enemy; // We need a forward declaration of your enemy
struct my_class {
// The access is done using a factory, where the caller has to tell
// us his own name
template <class T>
struct make{
static_assert(!std::is_same<T,enemy>::value,"you are my enemy.");
friend T;
private:
my_class operator() () { return my_class{}; }
};
private:
my_class(); // This is the constructor we care about
};
struct no_enemy {
void bar() {
my_class a = my_class::make<no_enemy>{}(); // works
}
};
struct enemy {
void bar() {
my_class b = my_class::make<enemy>{}(); // error: static_assert failed
my_class c = my_class::make<no_enemy>{}(); // error: foo is "private"
}
};
I have the following setup:
foo.h:
class A {
friend class B;
private:
A() {}
};
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
vector<A> myMember;
};
An object of A will never be exposed to any program including foo.h. The vector with A's is only there to help B in its computation adapter role. By making A's constructor private, I thought I could avoid other compilation units from using it, and it seems to work. However, the problem is in
foo.cpp
void B::computeResult(Result &r) {
MyCustomStorage<A> storage;
A *a = storage.allocate(); // error: "A::A() is private"
}
where part of MyCustomStorage looks like so:
template <typename T>
class MyCustomStorage {
T *allocate() {
...
T *ptr = new T[count]; // error: "A::A() is private"
...
}
};
But I thought since allocate() is called from a member function, this wouldn´t happen! How could I solve this?
Making A a friend to MyCustomStorage seems very spaghetti-codish. Making A a private nested class of B makes all sorts of help-classes in foo.cpp fail because "A is private".
So what would be the cleanest way to solve this?
SOLUTION
I ended up going with #potatoswatter 's second solution, with these appropriate changes:
foo.h
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
class A {
private:
A() {}
};
class Helper; // forward declared!
vector<A> myMember;
};
foo.cpp
class B::Helper {
int help(A& a) { return 42; } // no problem! Helper is a member of B
}
void B::computeResult(Result &r) {
MyCustomStorage<A> storage;
A *a = storage.allocate(); // no problem! A is a member of B
Helper h;
h.help(*a); // no problem!
}
It's not the constructor of A that is private, it's the entire class.
The best solution is to create a "private" namespace. C++ doesn't have namespace-level access protection, but it's reasonable to expect that users won't access an unfamiliar namespace.
namespace impl {
struct A {
A() {}
};
}
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
vector<impl::A> myMember;
};
Another approach is to make A a member of B. This offers "real" access protection at the expense of deeper nesting. I personally prefer the first solution, and to avoid nested classes.
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
struct A {
A() {}
};
vector<A> myMember;
};
Any helpers that need A would then need to be friends. There are various workarounds like nesting A in a base class with protected access, but really, namespace impl offers the least compromises.
IMHO, You have a couple options. You can either 1) Use the Pimpl idiom, or, 2) you can use forward declaration.
Pimpl Idiom Example:
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
class Impl;
Impl *pimpl;
};
And in your *.cpp file, you can define the Impl class and use it's guts.
class B::Impl {
public:
std::vector<A> stuff;
}
B::B() : pimpl(new Impl) {
}
B::~B() {
delete pimpl;
}
void B::AddObject(Object &o) {
pimpl->stuff.Fx(o);
}
You can also use a smart pointer for the Pimpl idiom, I just didn't here for the sake of clarity/brevity.
Forward declaration can also be used if A is in the same namespace as B
class B {
public:
void addObject(Object &o); // adds to myMember; A is not exposed!
void computeResult(Result &r); // uses myMember to compute result
private:
std::vector<class A*> myMember;
};
But this idiom is fundamentally different than your requirements and restricts you to using a pointer within your object myMember, which you may not want to do. Inline defining class A* is also a non-standard forward-declarative approach. Of course, use of smart pointers would reduce the possibility of memory-leaks at this location.
I have a class FooBar that contains a member of type Foo. This type can be inherited from so that FooBar has variable behaviour. Foo contains multiple overloads for the accessor method bar.
class FooBar;
class Foo{
friend class FooBar;
virtual void bar(int barIn){ bar_ = barIn; }
virtual void bar(int barIn, float barScale){ bar(int(barIn * barScale)); }
virtual void bar(const Foo& barSource){ bar(barSource.bar_); }
int bar(){ return bar_; }
int bar_;
};
class FooBar{
public:
void bar(int barIn){ foo_.bar(barIn); }
void bar(int barIn, float barScale){ foo_.bar(barIn, barScale); }
void bar(const Foo& barSource){ foo_.bar(barSource); }
int bar(){ return foo_.bar(); }
private:
Foo& foo_;
};
Looks ok so far, but I feel like all the definitions for the FooBar.bar accessor are kind of unnecessary. I know that the compiler inlines them, so there should be no overhead, but the methods all got the same name and are all overloads of each other.
Is there a way in C++ to "export" (I haven't found a better word) the accessor so calls to FooBar.bar are just redirected to FooBar.foo_.bar?
One idea I had was overriding the operator -> for FooBar, but the real case has multiple classes like Foo, so that would only work for one of them.
You could write a real generic forwarder:
class FooBar
{
public:
template<typename... Args>
auto bar(Args&&... args) -> decltype(foo_.bar(std::forward<Args>(args)...))
{
return foo_.bar(std::forward<Args>(args)...);
}
private:
Foo& foo_;
};
(this requires C++11, with C++14 you could even leave out the ->decltype... part)
For example, say I have the following code;
class Foo
{
public:
Foo(int x) : _foo(x)
{
}
private:
int _foo;
protected:
std::string _bar;
};
class Bar : public Foo
{
public:
Bar() : Foo(10), _temp("something"), _bar("something_else")
{
}
private:
std::string _temp;
};
int main()
{
Bar stool;
}
The code doesn't run because _bar is of the class Foo and it doesn't appear to know it exists, so is this not how you would go about doing it? Or would you just have _bar in Foo's constructor? This would work but what if _bar doesn't always have to be assigned something?
Edit: Below is the real code I was using;
Entity::Entity(GameState *state, bool collidable)
:_isLoaded(false), _state(state), alive(true), collidable(collidable), name(entityDetault)
{
}
Entity::Entity(GameState *state, bool collidable, entityName _name)
:_isLoaded(false), _state(state), alive(true), collidable(collidable), name(_name)
{
}
and then the child class would use this constructor;
Player::Player(GameState *state)
: Entity(state,true,entityName::entityPlayer), health(100),bulletSpeed(600),_colour(sf::Color(128,255,86,255))
Does this all look correct now? Slightly better than doing it all in the constructor body.
The member initialiser list in a constructor of class C can only initialise:
direct base classes of C
direct members of C
virtual base classes of C (doesn't come up too often)
The only way to initalise a member of a base class is through a constructor of the base class. Or just forego initialisation and then do an assignment in the body of C's constructor. The latter cannot be used for const members or references, though, and in general does not do the same thing as just initialisation.
You could either move it from the initializer list to the body (if it is not const):
Bar() : Foo(10), _temp("something")
{
_bar = "something_else";
}
or provide a second (maybe protected) contructor for Foo:
class Foo
{
public:
Foo(int x) : _foo(x)
{
}
protected:
Foo(int x,std::string s) : _foo(x), _bar(s)
{
}
private:
int _foo;
protected:
std::string _bar;
};
class Bar : public Foo
{
public:
Bar() : Foo(10,"something_else"), _temp("something")
{
}
private:
std::string _temp;
};
You need to initialize the base class before you can access it. If you want to initialize member variable in the base class, you have to do it via call to base class constructor in which will initialize it's members.
You may put _bar in Foo's constructor's initialization list. If _bar does not always need be to assigned something, you can use default value.
class Foo
{
public:
Foo(int x):_foo(x)
{
}
protected:
Foo(int x, string s) : _foo(x),_bar(s)
{
}
private:
int _foo;
protected:
std::string _bar;
};
class Bar : public Foo
{
public:
Bar() : Foo(10,"something else"), _temp("something")
{
}
private:
std::string _temp;
};
I have a set of classes that are replies from the network. Some classes uses function foo, while others use bar. I was thinking of just have a class that sets the variable inside foo and bar. Then inherit those classes which just only have function foo and bar functions without constantly defining the functions in those classes. For example.
class Foo {
public:
Foo():
foo_(std::string()) {}
virtual ~Foo(){}
const std::string& foo() const { return foo_; }
private:
std::string foo_;
};
class FooReply:
public Foo {
public:
FooReply(){}
explicit FooReply(const std::string& reply):
setFoo(reply) {
}
FooReply(const FooReply& other):
Foo(other) {
}
~FooReply(){}
FooReply& operator=(const FooReply& other) {
Foo::operator=(other);
return *this;
}
};
Would it be better to do this, or should I just make them an interface and just reimplement the foo() function? Since I'm only inheriting one function.