I'm currently creating a basic UI system for a game I'm writing. It's organized as a tree of nodes. I'm trying to write it so that only the root node can call the update method on other nodes. I thought I understood C++ inheritance but it's once again laughing at my incompetence. I've tried to create a bare-bones example below:
class Base
{
public:
virtual ~Base() { }
protected:
virtual void update_internal() = 0;
};
class Node_A : public Base
{
protected:
virtual void update_internal() { std::cout << "Update Node A" << std::endl; }
};
class Node_B : public Base
{
protected:
virtual void update_internal() { std::cout << "Update Node B" << std::endl; }
};
class Root : public Base
{
public:
void add_node (Base* node) { m_nodes.push_back(node); }
void update()
{
for (auto& node : m_nodes)
{
node->update_internal();
}
}
protected:
std::vector<Base*> m_nodes;
virtual void update_internal() { }
};
int main()
{
Node_A alpha_node;
Node_B beta_node;
Root root_node;
root_node.add_node(&alpha_node);
root_node.add_node(&beta_node);
root_node.update();
}
When I try to compile this GCC gives me the error:
error: 'virtual void Base::update_internal()' is protected
All of the nodes including root inherit the update_internal() method from Base, I don't understand why it matters that it is protected. I thought it was only private members and methods that derived classes couldn't access.
You can only call a protected/private function of a base class only from an instance of the derived class (unless of course you use friends). So the derived class can only access the private/protected members of its base part, not of some other base. In your case, you call it via a reference to a Base* in
for(auto& node : m_nodes)
node->update_internal();
so the compiler complains.
Just befriend Base and Root;
class Base
{
friend class Root; // <- yes,this
public:
virtual ~Base() { }
protected:
virtual void update_internal() = 0;
};
This is a stock example for the Template Method pattern.
The public method of the Root class exposes, what's needed to be implemented internally.
class Base
{
protected:
virtual void update_internal() = 0;
static void DoUpdate( Base *node )
{
node->update_internal();
}
};
class Root : public Base
{
public:
void update()
{
for (auto node : m_nodes)
{
Base::DoUpdate( node );
}
}
protected:
virtual void update_internal() override {}
std::vector<Base*> m_nodes;
};
Related
I have an abstract base class Node, which is derived from an abstract Interface class IObservable.
There is a several classes implementing the abstract IObservable: SingleObservable and MultiObservable
I want to create a class ObservableNode, derived from the base Node class and specify on its declaration which class to use for the implementation of the IObservable interface.
I've added using ... statements for every pure virtual method in IObservable, referring to the methods in the implementation classes but I still get errors saying that ObservableNode is an abstract class, missing the implementation of notifyObservers(IObject*).
If I add the parameter IObject* to the using statement I get an "expected ';' before '(' token" error
How can I solve this?
class IObservable {
public:
virtual ~IObservable() {};
virtual void notifyObservers(IObject*) = 0;
};
class SingleObservable: public IObservable {
public:
virtual ~SingleObservable() {};
void notifyObservers(IObject*) override {
//some implementaiton
};
};
class MultiObservable: public IObservable {
public:
virtual ~MultiObservable() {};
void notifyObservers(IObject*) override {
//some other implementaiton
};
};
class Node: public IObservable {
public:
virtual ~Node() {};
};
class ObservableNode: public Node, public SingleObservable {
public:
virtual ~ObservableNode() {};
using SingleObservable::notifyObservers;
// using SingleObservable::notifyObservers(IObject*); // expected ';' before '(' token error
};
Node* node = new ObservableNode() // instantiating abstract class error, missing notifyObservers(IObject*) implementation
Your problem seems to be that you inherit Node which is still abstract, and also causes to introduce the good old multimple inheritance vicious diamond problem. When I change your code like this, the error disappears:
class Node: public IObservable {
public:
virtual ~Node() {};
// ** Added an implementation here **
void notifyObservers(IObject*) override {
//some other implementaiton
};
};
class ObservableNode: public virtual Node, public virtual SingleObservable {
// ^^^^^^^ ^^^^^^^
public:
virtual ~ObservableNode() {};
using SingleObservable::notifyObservers;
};
int main() {
Node* node = new ObservableNode();
}
See it live on coliru.
#πάντα ῥεῖ's answer describe one workaround, but possible this is not what OP is after here. Also, as my comment describe under the answer, the approach in the answer might give unexpected results e.g. when invoking node->notifyObservers(obj):
Note that in this particular example, Node* node = new
ObservableNode(); will mean node->notifyObservers(obj) will invoke
Node::notifyObservers(IObject*) and not
SingleObservable::notifyObservers(IObject*), which might be
unexpected, considering we instantiate an ObservableNode object
which specifies using SingleObservable::notifyObservers;.
In OP's original code, we are suffering from multiple inheritance ambiguity, as we are not using virtual inheritance when Node and SingleObservable (and MultiObservable) derives from IObservable:
class SingleObservable: public IObservable {
public:
virtual ~SingleObservable() {};
void notifyObservers(IObject*) override {
//some implementaiton
};
};
class Node: public IObservable {
public:
virtual ~Node() {};
};
Meaning our the object's memory layout, w.r.t. inheritance, of ObservableNode to looks like the following
IObservable IObservable
| |
Node SingleObservable
\ /
ObservableNode
whereas, in this context, we are likely to want an object's memory layout looking as follows
IObservable
/ \
Node SingleObservable
\ /
ObservableNode
If we were to correct this, Node can stay abstract, and a call to node->notifyObservers(obj) with node as OP's example will result in invocation of SingleObservable::notifyObservers, as might have been expected.
class Node: public virtual IObservable {
// ↑↑↑↑↑↑↑
public:
virtual ~Node() {};
};
class SingleObservable: public virtual IObservable {
// ↑↑↑↑↑↑↑
public:
virtual ~SingleObservable() {};
void notifyObservers(IObject*) override {
std::cout << "SingleObservable::notifyObservers";
};
};
struct DummyObj : public IObject {};
int main() {
Node* node = new ObservableNode();
DummyObj obj;
node->notifyObservers(obj); // SingleObservable::notifyObservers
}
Note that we not need virtual inheritance for when ObservableNode derives from Node and SingleObservable.
Finally, if we'd want Node be non-abstract (specifically, to provide an override of void notifyObservers(IObject*)), then ObservableNode must provide it's own (final) override of it, as we will otherwise inherit two final overrides of it in ObservableNode (one from Node and one from SingleObservable). In this case, ObservableNode could simply define its own override which explicitly calls the base class of choice, e.g.
class Node: public virtual IObservable {
public:
virtual ~Node() {};
void notifyObservers(IObject*) override {
std::cout << "Node::notifyObservers";
};
};
class SingleObservable: public virtual IObservable {
public:
virtual ~SingleObservable() {};
void notifyObservers(IObject*) override {
std::cout << "SingleObservable::notifyObservers";
};
};
class ObservableNode: public Node, public SingleObservable {
public:
virtual ~ObservableNode() {};
// Non-ambiguous final override in ObservableNode.
// We could use `override` specifier here, but we might as well
// use `final`, if we are not expecting something to derive from ObservableNode.
void notifyObservers(IObject* obj) final {
SingleObservable::notifyObservers(obj);
};
};
struct DummyObj : public IObject {};
int main() {
Node* node = new ObservableNode();
DummyObj obj;
node->notifyObservers(obj); // SingleObservable::notifyObservers
}
See ISO C++ FAQ - Inheritance — Multiple and Virtual Inheritance for details on the diamond inheritance structure and virtual inheritance.
Thanks for all the suggestions! Implementing those caused a lot of other problems with other classes already using the Observable implementations, so I opted to solve it in a different manner, by including an implementation instance and delegating all methods to that one
class IObject {
public:
virtual ~IObject() {};
};
class IObservable {
public:
virtual ~IObservable() {};
virtual void notifyObservers(IObject*) = 0;
};
class SingleObservable: public IObservable {
public:
virtual ~SingleObservable() {};
void notifyObservers(IObject*) override {
std::cout << "Single\n";
//some implementaiton
};
};
class MultiObservable: public IObservable {
public:
virtual ~MultiObservable() {};
void notifyObservers(IObject*) override {
std::cout << "Multi\n";
//some other implementaiton
};
};
class Node: public IObservable {
public:
virtual ~Node() {};
// void notifyObservers(IObject*) override { };
};
class SingleObservableNode: public Node {
public:
SingleObservableNode() {};
virtual ~SingleObservableNode() {
delete obs;
};
void notifyObservers(IObject* obj) override {
obs->notifyObservers(obj);
}
private:
IObservable* obs = new SingleObservable();
};
class MultiObservableNode: public Node {
public:
MultiObservableNode() {};
virtual ~MultiObservableNode() {
delete obs;
};
void notifyObservers(IObject* obj) override {
obs->notifyObservers(obj);
}
private:
IObservable* obs = new MultiObservable();
};
Node* node1 = new SingleObservableNode();
Node* node2 = new MultiObservableNode();
int main()
{
node1->notifyObservers(nullptr); // "Single"
node2->notifyObservers(nullptr); // "Multi"
return 0;
}
This code demonstrates the problem:
class Base
{
public:
explicit Base(std::function<void()> const& printFunc) :
_printFunc(printFunc)
{
}
void print()
{
_printFunc();
}
private:
std::function<void()> _printFunc{};
private:
virtual void _print() = 0; // If this line is commented out, then
// `Subclass1::_print()` can be called.
};
class Subclass1 : public Base
{
public:
explicit Subclass1() :
Base([this]() { _print(); })
{
}
private:
void _print() /*override*/
{
std::cout << "Subclass1\n";
}
};
class Subclass2 : public Base, public Subclass1
{
public:
using fromLowestSubclass = Base;
public:
explicit Subclass2() :
Base([this]() { _print(); }), Subclass1()
{
}
private:
void _print() /*override*/
{
// Here is the problem:
Subclass1::print(); // or: static_cast<Subclass1*>(this)->print();
std::cout << "Subclass2\n";
}
};
int main()
{
Subclass2 sc2{};
sc2.fromLowestSubclass::print();
return 0;
}
In the Subclass2::_print method, the overriding _print method of Subclass1 should be called, but instead the Subclass1::print(); statement calls the current method again. This problem can be prevented if the statement virtual void _print() = 0; is commented out.
Why use of the virtual _print method prevents me from invoking the overloaded virtual method Subclass1::_print and what solution is there so that I do not have to do without virtual methods?
class Base
{
....
private:
virtual void _print() = 0;
}
This means: you can override _print, but you can't call it, only Base has right to call it.
Now:
class Base
{
public:
void print()
{
_printFunc();
}
does that, it calls _printFunc as a virtual function, which matches current object instantiation. It doesn't meter how print() was invoked.
Adding Subclass1:: as a prefix just changes name scope and doesn't have impact how method behaves. It has only have impact on name scope.
Now if virtual method has such prefix, then selecting name scope instruct compiler that you abandoning abstraction and you need to call specific method. In such case method is called without referring to a virtual table.
Double inheritance has no impact on this issue.
You can provide a helper method which you will be able to call from ancestor:
class Subclass1 : public Base
{
....
protected:
void sub1_print() // not virtual
{
std::cout << "Subclass1\n";
}
private:
void _print() /*override*/
{
sub1_print();
}
};
class Subclass2 : public Base, public Subclass1
{
....
private:
void _print() /*override*/
{
sub1_print();
std::cout << "Subclass2\n";
}
};
Let a class hierarchy :
class Base { virtual ~Base() throw(); };
class DerivedA : public Base { };
class DerivedB : public Base { };
I would like to have some code specific to each of these derived classes. However that code also being specific to the application that makes use of this class hierarchy, I do not want to embbed this derived-class-specific code into these derived classes. To avoid doing so, I thought about writing free functions :
void DerivedASpecificWork( DerivedA da );
void DerivedBSpecificWork( DerivedB db );
However, when given an instance of a derived class through a reference/pointer to a Base, I do not have access to the actual type of the instance, and thus cannot call the proper Derived*SpecificWork() function.
I would like to know if there is nome kind of design pattern that would allow me to call a derived-class-specific function without knowing the actual type of the instance, i.e having the same mechanism as virtual functions provide, but without having these virtual functions that would require me to embbed application-specific code into that class hierarchy.
Actually, why I want to do that is to provide informations about an exception that occured within a natively implemented function called by a Lua script. Each exception carrying its own set of information, the way I want to represent the error within the script depends on the type of the exception. I could create a pure virtual method in the base class that would be implemented by derived classes, but this would require me to embbed Lua-related code into my exception hierarchy, which I do not want to do since the Lua is specific to one of the application using that exception hierarchy.
Also I cannot use C++11.
Thank you.
May be Brigde pattern can help you.
This pattern can be used when you want to avoid a permanent binding between an abstraction and it's implementation.
(I don't see your comment about your restriction in using c++11, but you can remove std::unique_ptr, std::move and override keyword)
class AppSpecificImp
{
public:
virtual void DoWork() = 0;
};
class Base
{
public:
virtual ~Base() throw();
virtual DoWork() = 0;
};
class DerivedA : public Base
{
public:
DerivedA(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedA specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
class DerivedB : public Base
{
public:
DerivedB(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedB specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
Edit to show Visitor pattern usage:
With visitor pattern you can do what you want but with more Effort.
class Visitor
{
public:
virtual void VisitDerivedA(DerivedA* object) = 0;
virtual void VisitDerivedB(DerivedB* object) = 0;
};
class Base
{
public:
virtual void Visit(Visitor* visitor) = 0;
};
class DerivedA : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedA(this);
}
};
class DerivedB : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedB(this);
}
};
class AppSpecificVisitor : public Visitor
{
public:
void VisitDerivedA(DerivedA* object)
{
// Do any work related to DerivedA class
}
void VisitDerivedB(DerivedB* object)
{
// Do any work related to DerivedB class
}
}
int main()
{
AppSpecificVisitor myVisitor;
Base* myBase = // any class in your hierarchy
myBase->Visit(&myVisitor);
}
As I said in comments with Visitor pattern you can add new functionally without changing the main hierarchy(Base->Derived types). You just define a new visitor implementation and write your logic for every class in main hierarchy. In your example you can pack app specific logic in an object and reference that in your derived objects that is an easier approach.
Why not using a new set of hierarchy for application specific implementation ?
class AppBase
{
public:
virtual ~AppBase() throw();
virtual void work_with_app() = 0;
};
class Base
{
public:
Base(AppBase& app) : m_app(app) {}
virtual ~Base() throw();
protected:
AppBase& m_app;
};
class DerivedA : public Base { DerivedA(AppBase& app) : Base(app) {} };
class DerivedB : public Base { DerivedA(AppBase& app) : Base(app) {} };
// Application specific implementation :
class AppLuaSpecific : public AppBase
{
public:
void work_with_app() { /* Lua app specific */ }
};
This way, your 1st hierarchy : Base, DerivedA, DerivedB can live without knowing anything about the app specific code implemented in AppLuaSpecific.
You can implement your own app-specific dispatch as follows (check it live on Coliru):
#include <iostream>
#include <typeinfo>
struct Base { virtual ~Base() {} };
struct DerivedA : public Base { };
struct DerivedB : public Base { };
namespace AppSpecific
{
template<class F>
void dispatch(const Base& b)
{
const std::type_info& t = typeid(b);
if ( t == typeid(DerivedA) )
F::doit(static_cast<const DerivedA&>(b));
else if ( t == typeid(DerivedB) )
F::doit(static_cast<const DerivedB&>(b));
}
struct Foo
{
static void doit(const DerivedA& da) { std::cout << "Foo(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Foo(DerivedB)\n"; }
};
struct Bar
{
static void doit(const DerivedA& da) { std::cout << "Bar(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Bar(DerivedB)\n"; }
};
} // namespace AppSpecific
int main()
{
DerivedA da;
DerivedB db;
Base& b1 = da;
Base& b2 = db;
AppSpecific::dispatch<AppSpecific::Foo>(b1);
AppSpecific::dispatch<AppSpecific::Foo>(b2);
AppSpecific::dispatch<AppSpecific::Bar>(b1);
AppSpecific::dispatch<AppSpecific::Bar>(b2);
}
Say I have a parent class Parent and child classes Child1 and Child2 having the latter implementing MyInterface:
class Parent {
public:
Parent();
virtual ~Parent();
virtual void MyMethod();
}
class MyInterface {
public:
virtual ~MyInterface() {}
virtual void MyInterfaceMethod() = 0;
}
class Child1 : public Parent {
public:
Child1();
virtual ~Child1();
}
class Child2 : public Parent, MyInterface {
public:
Child2();
virtual ~Child2();
virtual void MyInterfaceMethod() override;
}
And say I'm given a Parent* pointer, and I want to check if the object is implementing MyInterface and if yes, cast it to MyInterface*.
I've tried to achieve it this way:
void MyFunction(Parent* p) {
MyInterface* i = dynamic_cast<MyInterface*>(p);
if (i != 0)
DoSomething();
else
cout << "Cannot do anything.";
}
But i always equals to 0 which says it is never casted to the type MyInterface* even if I know for sure that the object has the good type.
How should I achieve this?
Child2 private inherits from MyInterface, unless MyFunction() has the privilege to access the private base subobject, dynamic_cast will always fail.
Since MyInterface seems to be an interface, I think you want public inheritance.
class Child2 : public Parent, public MyInterface { }
// ~~~~~~
LIVE (Other errors fixed)
Your classes must be polymorphic types for dynamic_cast to work.
The simplest way of achieving this is to add
virtual ~Parent() = default;
in the public area of the Parent class. Then the dynamic_cast will sniff around the inheritance tree for your interface like a truffling pig.
Alternatively, instead of using dynamic_cast, we could use the Visitor Pattern:
#include <iostream>
class MyInterface {
public:
virtual void DoSomething() = 0;
};
class Parent {
public:
virtual ~Parent() = default;
virtual void accept(class Visitor& visitor) = 0;
};
class Child1 : public Parent {
public:
virtual void accept(Visitor& visitor);
};
class Child2 : public Parent, public MyInterface {
public:
virtual void accept(Visitor& visitor);
virtual void DoSomething();
};
class Visitor
{
public:
void visit(Child1& child);
void visit(Child2& child);
};
void Child1::accept(Visitor& visitor) { visitor.visit(*this); }
void Child2::accept(Visitor& visitor) { visitor.visit(*this); }
void Child2::DoSomething() { std::cout << "Do something.\n"; }
void Visitor::visit(Child1& child) { std::cout << "Cannot do anything.\n"; }
void Visitor::visit(Child2& child) { child.DoSomething(); }
void MyFunction(Parent& p) {
Visitor v;
p.accept(v);
}
int main()
{
Child1 c1;
Child2 c2;
MyFunction(c1);
MyFunction(c2);
}
Output:
Cannot do anything.
Do something.
I have a hierarchy of nodes, where "diamond" can occurred.
Every node must be clonable but I don't want to write clone method to every node. So I use CRTP.
class Node
{
public:
Node(){}
Node(Fill*) { }
virtual ~Node() {}
virtual Node * clone() const = 0;
virtual void id() { std::cout << "Node\n"; }
};
//====================================================================
template <typename Base, typename Derived>
class NodeWrap : public Base
{
public:
NodeWrap() { }
NodeWrap(Fill * arg1) : Base(arg1) { }
virtual Node *clone() const
{
return new Derived(static_cast<Derived const &>(*this));
}
};
works as follows:
class NodeA : public NodeWrap<Node, NodeA>
{
public:
typedef NodeWrap<Node, NodeA> BaseClass;
NodeA() { }
NodeA(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeA\n"; }
};
First question:
There is know BUG in VS when "covariance is used with virtual inheritance".
Is there a way to overcome the bug, and still have covariant types is clone method?
I changed return type to be Node instead of Base. I can live with that, but I would like to have Base as return type
Second question:
Problem occurred when multiple inheritance comes to play. I created new wrapper, which inherits virtually
template <typename Base, typename Derived>
class NodeWrapVirtual : public virtual Base
{
public:
NodeWrapVirtual() { }
NodeWrapVirtual(Fill * arg1) : Base(arg1) { }
virtual Node *clone() const
{
return new Derived(static_cast<Derived const &>(*this));
}
};
and now building diamond structure:
class NodeB : public NodeWrapVirtual<Node, NodeB>
{
public:
typedef NodeWrapVirtual<Node, NodeB> BaseClass;
NodeB() { }
NodeB(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeB\n"; }
};
//====================================================================
class NodeC : public NodeWrapVirtual<Node, NodeC>
{
public:
typedef NodeWrapVirtual<Node, NodeC> BaseClass;
using BaseClass::clone;
NodeC() { }
NodeC(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeC\n"; }
};
and problematic diamond node:
class NodeD : public NodeWrap<NodeB, NodeD>,
public NodeWrap<NodeC, NodeD>
{
public:
typedef NodeWrap<NodeB, NodeD> BaseClassB;
typedef NodeWrap<NodeC, NodeD> BaseClassC;
NodeD() { }
NodeD(Fill * f) : BaseClassB(f), BaseClassC(f) { }
using BaseClassB::clone; // (1)
virtual NodeD *clone() const { return new NodeD(*this); } // (2)
virtual void id() { std::cout << "NodeD\n"; }
};
where are 2 lines I am curious about. (line (1) and (2))
If both lines are removed, there is oblivious compile error, because there is ambiguous clone method (from every parent). Since I don't use covariant return types, there should work clone method form each parent, so i use line (1) but it doesn't work. Still ambiguous.
So I use line (2) and it works.
Is there a nice way, to avoid writing line (2)?
HERE is full working example on ideone.
First you should be very carefull to use virtual inheritance with members inside the virtual base (look at https://stackoverflow.com/a/1193516/1918154, "Effective C++", item 20: "Avoid data members in public interfaces" and http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.8). Your node gets an pointer to a fill which is not used, but it looks like you need it somewhere.
Your problem can be solved when you move the inhertance relationship (public virtual and public) in the base class for your NodeWrap.
template <typename Base>
class InheritVirtual
: public virtual Base
{};
template <typename... Bases>
class InheritBases
: public Bases...
{
virtual Node* clone() const = 0;
virtual void id() const = 0;
};
class NodeB : public NodeWrap<InheritVirtual<Node>, NodeB>
{
//...
};
class NodeC : public NodeWrap<InheritVirtual<Node>, NodeB>
{
//...
};
class NodeD : public NodeWrap<InheritBases<NodeB,NodeC>, NodeD>
{
//...
};
Running Example.
The pure virtual methods in InheritBases are needed because the so called domination rule (Dominance in virtual inheritance).
The problem to be solved is a way to transfer paramters to the right constructor in case of multiple bases. Unlike Node (wich is a virtual base) it is ok to let NodeB and NodeC have member variables and non trivial constructors.
Each virtual function must have a unique final overrider in each derived class. This has nothing to do with name lookup (the requirement is for the functions, not for their names), thus using is irrelevant.
Use a multi-base-classed node class template:
template <class Derived, class Base1, class Base2>
class node2 : // etc
// or use a variadic template if you have more than two bases
As for covariant returns, they are strictly unnecessary, if convenient. You can always split each virtual function into a private virtual and a public non-virtual. This comes handy if you want to return covariant smart pointers, which is not supported by the regular covariant return machinery at all.