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.
My code structure is like below where multiple classes implement Interface. In Example class I store a pointer to the Interface and new() it in the constructor appropriately (depending on constructor parameters not shown here). I'm looking for ways to avoid using new() in this scenario but haven't got a solution yet. What's the best practice for something like this?
class Interface
{
virtual void Foo() = 0;
};
class A : public Interface
{
void Foo() { ... }
};
class B : public Interface
{
void Foo() { ... }
};
class Example
{
private:
Interface* m_bar;
public:
Example()
{
m_bar = new A(); // deleted in destructor
}
};
There are two ways this is typically done, each with their own merits.
If A is truely defined at compile time, than a typical way to handle this is to simply use a template type:
template <typename T>
class TemplateExample
{
T m_bar;
public:
TemplateExample() : m_bar() {};
}
This has some downsides. TemplateExample<A> becomes unrelated to TemplateExample<B>, the error messages when T doesn't follow the correct interface are pretty obtuse, ect. The upside is this may use duck typing rather than interface typing, and m_bar is a concrete instance.
The other (arguable more common) way is to do the following
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
};
This has the benefit of being able to be run time configuratble if you follow a cloable pattern:
class Interface
{
public:
virtual void Foo() = 0;
virtual Interface* clone() const = 0;
};
template <typename T>
class CloneHelper : public Interface
{
public:
virtual Interface* clone() const { return new T(static_cast<const T&>(*this));}
};
class A : public CloneHelper<A>
{
virtual void Foo() { std::cout << 'A' << std::endl; }
};
class B : public CloneHelper<B>
{
virtual void Foo() { std::cout << 'B' << std::endl; }
};
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
UniquePtrExample(const Interface& i) : m_bar(i.clone());
};
Note you can further extend the above to have a move variant of the clone function.
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)
I have a data structure, and two classes accessing it:
class Foo {
public:
void set(double foo);
double get();
};
class FooWriter {
Foo bar;
void setFoo() { bar.set(42); }
};
class FooReader {
Foo *baz;
double getFoo() { return baz->get(); }
};
I would like to restrict FooReader to read Foo, and allow setting only for FooWriter. Private set function and friend class would be an option but unfortunately I have a lot of subclasses of FooWriter, and since friendship can not be inherited, I would not like to list them all as friends. Bypassing encapsulation with protected method in friend FooWriter superclass is an other option:
class Foo {
void set(double foo);
public:
double get();
friend class FooWriter;
};
class FooWriter {
Foo bar;
protected:
void setFooBackdoor(double value) { bar.set(value); }
};
class subFooWriter {
void setFoo() { setFooBackdoor(42); }
};
but some would consider this as bad design. I've also read here that if you need friendship inheritence, there is a flaw in your design, so I'm curious, what would be the proper solution for this problem.
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;
};