So, I have code like this:
class IUpdatable {
virtual void onUpdate() = 0;
};
class IDrawable {
virtual void onDraw() = 0;
};
class IEventable {
virtual void onEvent() = 0;
};
class IObject {};
class Button : public IObject, public IUpdatable, public IDrawable, public IEventable {/*override of virtual metothods*/};
class NonVisibleButton : public IObject, public IUpdatable, public IEventable {/*override of virtual methods*/}
int main(){
std::vector <std::shared_ptr <IObject>> buttons = {
new Button(),
new NonVisibleButton()
};
std::vector <std::weak_ptr <IEventable>> eventables = {
buttons.at(0),
buttons.at(1)
};
std::vector <std::weak_ptr <IDrawble>> drawbles = {
buttons.at(0)
};
}
So, can I realize this and how? I want to regulary update vector with buttons in the different containers. (to be more precise, I have individual thread for updating IEventable's child class' objects and absolutely everything that inherits from IEventable goes here)
Something like this could work:
#include <vector>
#include <memory>
class IUpdatable {
public:
virtual void onUpdate() = 0;
};
class IDrawable {
public:
virtual void onDraw() = 0;
};
class IEventable {
public:
virtual void onEvent() = 0;
};
class IObject {
public:
virtual ~IObject() = default;
};
class Button : public IObject, public IUpdatable, public IDrawable, public IEventable {
public:
void onUpdate() override {}
void onDraw() override {}
void onEvent() override {}
};
class NonVisibleButton : public IObject, public IUpdatable, public IEventable {
public:
void onUpdate() override {}
void onEvent() override {}
};
int main(){
std::vector <std::shared_ptr <IObject>> buttons = {
std::static_pointer_cast<IObject>(std::make_shared<Button>()),
std::static_pointer_cast<IObject>(std::make_shared<NonVisibleButton>())
};
std::vector <std::weak_ptr <IEventable>> eventables = {
std::dynamic_pointer_cast<IEventable>(buttons.at(0)),
std::dynamic_pointer_cast<IEventable>(buttons.at(1))
};
std::vector <std::weak_ptr <IDrawable>> drawbles = {
std::dynamic_pointer_cast<IDrawable>(buttons.at(0))
};
}
Honestly though, I wouldn't try to shoehorn a Java code structure (interfaces, inheritance, etc) into C++... Try composition over inheritance if possible.
Use local variables to hold the Button and NonVisibleButton. That has the added benefit of not needing buttons.at to refer to them.
int main(){
auto b = std::make_shared<Button>();
auto nvb = std::make_shared<NonVisibleButton>();
std::vector <std::shared_ptr <IObject>> buttons = {
b,
nvb
};
std::vector <std::weak_ptr <IEventable>> eventables = {
b,
nvb
};
std::vector <std::weak_ptr <IDrawble>> drawbles = {
b
};
}
Related
i know there is nothing like virtual template method in C++, but as it seems it is exactly what i need. Is there any workaround i could use? I am thankful for any suggestion.
I would like to add Entities to a vector by a add method, which need to be virtual and also template, how to avoid this?
#include <iostream>
#include <vector>
class EntityBase {
public:
};
class EntityDerived1 : public EntityBase {
public:
};
class EntityDerived2 : public EntityBase {
public:
};
class ContainerBase {
public:
template<typename T>
virtual void add() = 0; // i know this is not allowed!!!
};
class ContainerConcrete : public ContainerBase {
public:
template<typename T>
void add() override { // i know this is not allowed!!!
data.push_back(std::make_shared<T>());
}
void doSecretStuffWithDataHere() {
// ...
}
private:
std::vector<std::shared_ptr<EntityBase>> data;
};
class Engine {
public:
Engine() :
container(std::make_shared<ContainerConcrete>())
{}
ContainerBase& getContainer() {
auto rawPointer = container.get();
return *container;
}
private:
std::shared_ptr<ContainerConcrete> container;
};
int main() {
Engine engine;
ContainerBase& container = engine.getContainer();
container.add<EntityDerived1>();
container.add<EntityDerived2>();
}
Just make add a regular virtual function that takes shared_ptr as a parameter
class ContainerBase {
public:
virtual void add(std::shared_ptr<EntityBase>) = 0;
};
class ContainerConcrete : public ContainerBase {
public:
void add(std::shared_ptr<EntityBase> p) override {
data.push_back(p);
}
// . . .
And then invoke it with make_shared for the desired type:
int main() {
Engine engine;
ContainerBase& container = engine.getContainer();
container.add(std::make_shared<EntityDerived1>());
container.add(std::make_shared<EntityDerived2>());
}
Alternatively you can add a templated overload that invokes make_shared:
virtual void add(std::shared_ptr<EntityBase>) = 0;
template<typename T>
void add() {
add(std::make_shared<T>());
}
I have a class hierarchy like:
class A {
list<A*> children;
public:
void update() {
do_something();
update_current();
for(auto child : children)
children->update();
}
protected:
virtual void update_current() {};
};
class B : public A {
protected:
void update_current() override {
do_something_important();
};
};
class C1 : public B {
protected:
void update_current() override {
B::update_current();
do_something_very_important();
};
};
class C2 : public B {
protected:
void update_current() override {
B::update_current();
do_something_very_important_2();
};
};
int main() {
A* a = new A();
//fill a's childred list somehow
while(come_condition) {
//some code
a.update();
//something else
}
return 0;
}
The question is: how can I remove duplicate B::update_current(); calls from derived classes without changing program's behaviour? Is it possible or are there no solutions except calling base class functions manually? Thank you.
You could make B's children override a different function:
class B : public A {
protected:
void update_current() override final {
do_something_important();
do_something_important_later();
};
virtual void do_something_important_later() = 0;
};
With:
class C2 : public B {
protected:
void do_something_important_later() override {
do_something_very_important_2();
};
};
class Base{
protected:
int remainItems = 0;
public:
Base(){}
virtual int numOfItem() = 0;
};
class Deveried1 : public Base{
public:
Deveried1() :Base(){ remainItems = numOfItem(); }
int numOfItem(){
return 5;
}
};
class Deveried2 : public Base{
public:
Deveried2() :Base(){ remainItems = numOfItem(); }
int numOfItem(){
return 10;
}
};
class Deveried3 : public Base{
public:
Deveried3() :Base(){ remainItems = numOfItem(); }
int numOfItem(){
return 10;
}
};
int main(){
Base* foo = new Deveried3;
}
With this design, for every deveried class, I must do the same thing in constructor to initalize remainItems. I'd like to know if there are some better way/pattern in this situation.
Indeed, you can't call derived class functions from the base class constructor, so this kind of twisted inversion of dependencies can't work. I'd pass the value to the base-class constructor:
Base(int numOfItems) : remainItems(nomOfItems) {}
Derived1() : Base(5) {}
Derived2() : Base(10) {}
I do not see any benefit in the method, so I removed it and added an option to pass the variable in the base class constructor:
class Base{
protected:
int remainItems;
public:
Base(remainItems = 0) { this->remainItems = remainItems; }
};
class Deveried1 : public Base{
public:
Deveried1() :Base(5){}
}
};
class Deveried2 : public Base{
public:
Deveried2() :Base(10){}
}
};
class Deveried3 : public Base{
public:
Deveried3() :Base(10){}
}
};
int main(){
Base* foo = new Deveried3;
}
I believe what you're looking for is called the Non-Virtual Interface pattern.
How to implement an interface class using the non-virtual interface idiom in C++?
I am new to Design Pattern, and I'm trying the first example of (Head First Design Patterns) but I'm trying to code it in C++. I can't compile my code! I don't know why. Here's my code.
#include <iostream>
using namespace std;
class QuackBehavior
{
public:
virtual void quack();
virtual ~QuackBehavior();
};
class Quack : public QuackBehavior
{
public:
void quack()
{
cout<<"Quacking"<<endl;
}
};
class MuteQuack : public QuackBehavior
{
public:
void quack()
{
cout<<"<<< Silence >>>"<<endl;
}
};
class Squeak : public QuackBehavior
{
public:
void quack()
{
cout<<"Squeak"<<endl;
}
};
class FlyBehavior
{
public:
virtual void fly();
virtual ~FlyBehavior();
};
class FlyWithWings : public FlyBehavior
{
public:
void fly()
{
cout<<"I'm flying"<<endl;
}
};
class FlyNoWay : public FlyBehavior
{
public:
void fly()
{
cout<<"I can't fly"<<endl;
}
};
class Duck
{
public:
FlyBehavior *flyBehavior;
QuackBehavior *quackBehavior;
void display();
void performFly()
{
flyBehavior->fly();
}
void performQuack()
{
quackBehavior->quack();
}
};
class MallardDuck : public Duck
{
public:
MallardDuck()
{
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
};
int main()
{
Duck *mallard = new MallardDuck;
cout<<"Test"<<endl;
mallard->performFly();
// mallard->performQuack();
return 0;
}
Thanks for your help.
You get a compile error because you have not provided default definitions for functions in class QuackBehavior and class FlyBehavior.
Either you could provide default implementation or make the functions pure virtual.
Make the below two changes and your code should compile fine.
class QuackBehavior
{
public:
virtual void quack(){}
virtual ~QuackBehavior(){}
};
class FlyBehavior
{
public:
virtual void fly(){}
virtual ~FlyBehavior(){}
};
OR
class FlyBehavior
{
public:
virtual void fly() = 0;
};
class QuackBehavior
{
public:
virtual void quack() = 0;
};
I want to reconstruct my small 3d-engine, it is very small so i place all files in only one project.
now, i want to reconstruct it with interfaces, so i can disperse different modules to the different projects and build them as a dll.
when i do that, i have met a lot of difficulties in the basic design of framework code.
I want to design a 'Object Hierarchy' of my small engine, it is realized in the previous work. for example:
Object
Component
SceneComponent
StaticMeshComponent/SkelMeshComponent
D3DSkelComponent
...
but they are implement directly.
now, i want to use interface(pure virtual class), i have design the basic interfaces(for test ):
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
class IObject
{
public:
virtual std::string GetName() = 0;
};
class IMesh : public IObject
{
public:
virtual void Draw() = 0;
};
class IStaticMesh : public IMesh
{
public:
virtual void BuildSomeMesh() = 0;
};
class ISkeletalMesh : public IMesh
{
public:
virtual void PlayAnim( const std::string& strAnimName ) = 0;
};
class ID3DSkeletalMesh : public ISkeletalMesh
{
public:
virtual void LoadD3D( const std::string& strD3D ) = 0;
};
it looks like ok, but when i try to implement them, i find that it may be a impossible mission.
first, i can write a template class or normal class for IObject, eg:
template < typename TBase >
class TObject : public TBase
{
public:
virtual std::string GetName()
{
return m_strTest;
}
std::string m_strTest;
};
based on this TObject, I can implement a CMesh:
class CMesh : public TObject< IMesh >
{
public:
virtual void Draw()
{
cout<<"draw mesh" <<endl;
}
};
IMesh* pMesh = new CMesh(); // ok
IObject* pObj = pMesh; // ok
so far, it works well. but how to implement the CStaticMesh/CSkeletalMesh/CD3DSkeletalMesh?
it maybe like this:
class CStaticMesh : public CMesh, public IStaticMesh
{
public:
};
but i have two IObject base class, so i must change all "public xxx" to "virtual public xxx", it looks bad.
another question is CStaticMesh must implement all virtual member function of IStaticMesh, include:
virtual void Draw() = 0;
virtual void BuildSomeMesh() = 0;
even if there is a Draw in CMesh which is a base call of CStaticMesh.
ok, maybe i need a TMesh:
template < typename TBase >
class TMesh : public TObject< TBase >
{
public:
virtual void Draw()
{
cout<<"draw mesh" <<endl;
}
};
and implement CStaticMesh like this:
class CStaticMesh : public TMesh<IStaticMesh>
{
public:
virtual void BuildSomeMesh()
{
cout<<"Build Some Mesh!"<<endl;
}
};
it looks like ok, but how to implment CD3DSkeletalMesh? make a TSkeletalMesh? ok, it is crazy!!!
i think, this is abime.
which is the mistake in this design? how to change the design idea to avoid this dilemma? do you know a idea which can keep the inheritance hierarchy of those interfaces and implement easily?
if i use many virtual inheritance, is there any performance isuue?
You can solve this, as you mentioned, with virtual inheritance. This will create only one instance of a multiply inherited interface class in the hierarchy.
First the interfaces:
class IObject
{
public:
virtual std::string GetName() = 0;
};
class IMesh : virtual public IObject
{
public:
virtual void Draw() = 0;
};
class IStaticMesh : virtual public IMesh
{
public:
virtual void BuildSomeMesh() = 0;
};
class ISkeletalMesh : virtual public IMesh
{
public:
virtual void PlayAnim( const std::string& strAnimName ) = 0;
};
class ID3DSkeletalMesh : virtual public ISkeletalMesh
{
public:
virtual void LoadD3D( const std::string& strD3D ) = 0;
};
Then the implementations:
class CObject : virtual public IObject
{
public:
std::string GetName()
{
return m_strTest;
}
std::string m_strTest;
};
class CMesh : public CObject, virtual public IMesh
{
public:
void Draw()
{
cout<<"draw mesh" <<endl;
}
};
class CStaticMesh : public CMesh, virtual public IStaticMesh
{
public:
void BuildSomeMesh()
{
cout<<"Build Some Mesh!"<<endl;
}
};
...
For the performance implications of this, look at this question.