How to delegate to implementing classIn C++, what is a virtual base class?How do you set, clear, and toggle a single bit?How do I iterate over the words of a string?Why can templates only be implemented in the header file?Safely override C++ virtual functionsDo ALL virtual functions need to be implemented in derived classes?How do you handle a “cannot instantiate abstract class” error in C++?Inheritance from empty base class in C++Can I have a virtual function that must be overridden from a non-abstract baseAbstract base class definitionHow to ensure that derivative classes implement particular methods, retaining standard layout?
How to creep the reader out with what seems like a normal person?
How would one muzzle a full grown polar bear in the 13th century?
Is there anything in our scriptures where it says something similar to "As a man thinketh in his heart, so is he"
What is the most expensive material in the world that could be used to create Pun-Pun's lute?
Alternatives to Overleaf
Can solid acids and bases have pH values? If not, how are they classified as acids or bases?
Stop and Take a Breath!
How can Republicans who favour free markets, consistently express anger when they don't like the outcome of that choice?
How much cash can I safely carry into the USA and avoid civil forfeiture?
How could Tony Stark make this in Endgame?
Phrase for the opposite of "foolproof"
Do vanished people know what happened after the snap?
How to pronounce 'C++' in Spanish
Binary Numbers Magic Trick
Why the difference in metal between 銀行 and お金?
How can the Zone of Truth spell be defeated without the caster knowing?
A Note on N!
Can someone publish a story that happened to you?
Is DC-to-DC (24 V to 12 V) buck conversion typically more efficient than AC-to-DC (110 V to 12 V) conversion?
How do I deal with a coworker that keeps asking to make small superficial changes to a report, and it is seriously triggering my anxiety?
Was there a Viking Exchange as well as a Columbian one?
Was there a shared-world project before "Thieves World"?
How to make a pipeline wait for end-of-file or stop after an error?
how to interpret this t result?
How to delegate to implementing class
In C++, what is a virtual base class?How do you set, clear, and toggle a single bit?How do I iterate over the words of a string?Why can templates only be implemented in the header file?Safely override C++ virtual functionsDo ALL virtual functions need to be implemented in derived classes?How do you handle a “cannot instantiate abstract class” error in C++?Inheritance from empty base class in C++Can I have a virtual function that must be overridden from a non-abstract baseAbstract base class definitionHow to ensure that derivative classes implement particular methods, retaining standard layout?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
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
c++
add a comment |
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
c++
add a comment |
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
c++
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
c++
c++
edited 1 hour ago
Bascy
asked 1 hour ago
BascyBascy
99211034
99211034
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
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.
@Scheff THX adopted it. Not to inheritNode
fromIObservable
would be certainly an alternative solution. You may still post that as an answer.
– πάντα ῥεῖ
1 hour ago
That indeed solved the problem, thanks! And indeed, I do want the IObservable interface in the Node definition
– Bascy
1 hour ago
1
Note that in this particular example,Node* node = new ObservableNode();
will meannode->notifyObservers(obj)
will invokeNode::notifyObservers(IObject*)
and notSingleObservable::notifyObservers(IObject*)
, which might be unexpected, considering we instantiate anObservableNode
object which specifiesusing SingleObservable::notifyObservers;
. What OP might possible want is to, inObservableNode
, define annotifyObservers(IObject*)
override which explictly forwards toSingleObservable::notifyObservers(IObject*)
.
– dfri
1 hour ago
1
... then a callnode->notifyObservers(obj)
will go down the vtable toObservableNode::notifyObservers(IObject*)
, and from there explicitly up to (by forwarding)SingleObservable::notifyObservers(IObject*)
.
– dfri
1 hour ago
1
@dfri THX for adding this information.
– πάντα ῥεῖ
1 hour ago
|
show 1 more comment
@πάντα ῥεῖ'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
will mean
ObservableNode();node->notifyObservers(obj)
will invoke
Node::notifyObservers(IObject*)
and not
SingleObservable::notifyObservers(IObject*)
, which might be
unexpected, considering we instantiate anObservableNode
object
which specifies usingSingleObservable::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.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55890369%2fhow-to-delegate-to-implementing-class%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
@Scheff THX adopted it. Not to inheritNode
fromIObservable
would be certainly an alternative solution. You may still post that as an answer.
– πάντα ῥεῖ
1 hour ago
That indeed solved the problem, thanks! And indeed, I do want the IObservable interface in the Node definition
– Bascy
1 hour ago
1
Note that in this particular example,Node* node = new ObservableNode();
will meannode->notifyObservers(obj)
will invokeNode::notifyObservers(IObject*)
and notSingleObservable::notifyObservers(IObject*)
, which might be unexpected, considering we instantiate anObservableNode
object which specifiesusing SingleObservable::notifyObservers;
. What OP might possible want is to, inObservableNode
, define annotifyObservers(IObject*)
override which explictly forwards toSingleObservable::notifyObservers(IObject*)
.
– dfri
1 hour ago
1
... then a callnode->notifyObservers(obj)
will go down the vtable toObservableNode::notifyObservers(IObject*)
, and from there explicitly up to (by forwarding)SingleObservable::notifyObservers(IObject*)
.
– dfri
1 hour ago
1
@dfri THX for adding this information.
– πάντα ῥεῖ
1 hour ago
|
show 1 more comment
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.
@Scheff THX adopted it. Not to inheritNode
fromIObservable
would be certainly an alternative solution. You may still post that as an answer.
– πάντα ῥεῖ
1 hour ago
That indeed solved the problem, thanks! And indeed, I do want the IObservable interface in the Node definition
– Bascy
1 hour ago
1
Note that in this particular example,Node* node = new ObservableNode();
will meannode->notifyObservers(obj)
will invokeNode::notifyObservers(IObject*)
and notSingleObservable::notifyObservers(IObject*)
, which might be unexpected, considering we instantiate anObservableNode
object which specifiesusing SingleObservable::notifyObservers;
. What OP might possible want is to, inObservableNode
, define annotifyObservers(IObject*)
override which explictly forwards toSingleObservable::notifyObservers(IObject*)
.
– dfri
1 hour ago
1
... then a callnode->notifyObservers(obj)
will go down the vtable toObservableNode::notifyObservers(IObject*)
, and from there explicitly up to (by forwarding)SingleObservable::notifyObservers(IObject*)
.
– dfri
1 hour ago
1
@dfri THX for adding this information.
– πάντα ῥεῖ
1 hour ago
|
show 1 more comment
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.
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.
edited 1 hour ago
answered 1 hour ago
πάντα ῥεῖπάντα ῥεῖ
74.6k1078146
74.6k1078146
@Scheff THX adopted it. Not to inheritNode
fromIObservable
would be certainly an alternative solution. You may still post that as an answer.
– πάντα ῥεῖ
1 hour ago
That indeed solved the problem, thanks! And indeed, I do want the IObservable interface in the Node definition
– Bascy
1 hour ago
1
Note that in this particular example,Node* node = new ObservableNode();
will meannode->notifyObservers(obj)
will invokeNode::notifyObservers(IObject*)
and notSingleObservable::notifyObservers(IObject*)
, which might be unexpected, considering we instantiate anObservableNode
object which specifiesusing SingleObservable::notifyObservers;
. What OP might possible want is to, inObservableNode
, define annotifyObservers(IObject*)
override which explictly forwards toSingleObservable::notifyObservers(IObject*)
.
– dfri
1 hour ago
1
... then a callnode->notifyObservers(obj)
will go down the vtable toObservableNode::notifyObservers(IObject*)
, and from there explicitly up to (by forwarding)SingleObservable::notifyObservers(IObject*)
.
– dfri
1 hour ago
1
@dfri THX for adding this information.
– πάντα ῥεῖ
1 hour ago
|
show 1 more comment
@Scheff THX adopted it. Not to inheritNode
fromIObservable
would be certainly an alternative solution. You may still post that as an answer.
– πάντα ῥεῖ
1 hour ago
That indeed solved the problem, thanks! And indeed, I do want the IObservable interface in the Node definition
– Bascy
1 hour ago
1
Note that in this particular example,Node* node = new ObservableNode();
will meannode->notifyObservers(obj)
will invokeNode::notifyObservers(IObject*)
and notSingleObservable::notifyObservers(IObject*)
, which might be unexpected, considering we instantiate anObservableNode
object which specifiesusing SingleObservable::notifyObservers;
. What OP might possible want is to, inObservableNode
, define annotifyObservers(IObject*)
override which explictly forwards toSingleObservable::notifyObservers(IObject*)
.
– dfri
1 hour ago
1
... then a callnode->notifyObservers(obj)
will go down the vtable toObservableNode::notifyObservers(IObject*)
, and from there explicitly up to (by forwarding)SingleObservable::notifyObservers(IObject*)
.
– dfri
1 hour ago
1
@dfri THX for adding this information.
– πάντα ῥεῖ
1 hour ago
@Scheff THX adopted it. Not to inherit
Node
from IObservable
would be certainly an alternative solution. You may still post that as an answer.– πάντα ῥεῖ
1 hour ago
@Scheff THX adopted it. Not to inherit
Node
from IObservable
would be certainly an alternative solution. You may still post that as an answer.– πάντα ῥεῖ
1 hour ago
That indeed solved the problem, thanks! And indeed, I do want the IObservable interface in the Node definition
– Bascy
1 hour ago
That indeed solved the problem, thanks! And indeed, I do want the IObservable interface in the Node definition
– Bascy
1 hour ago
1
1
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;
. What OP might possible want is to, in ObservableNode
, define an notifyObservers(IObject*)
override which explictly forwards to SingleObservable::notifyObservers(IObject*)
.– dfri
1 hour ago
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;
. What OP might possible want is to, in ObservableNode
, define an notifyObservers(IObject*)
override which explictly forwards to SingleObservable::notifyObservers(IObject*)
.– dfri
1 hour ago
1
1
... then a call
node->notifyObservers(obj)
will go down the vtable to ObservableNode::notifyObservers(IObject*)
, and from there explicitly up to (by forwarding) SingleObservable::notifyObservers(IObject*)
.– dfri
1 hour ago
... then a call
node->notifyObservers(obj)
will go down the vtable to ObservableNode::notifyObservers(IObject*)
, and from there explicitly up to (by forwarding) SingleObservable::notifyObservers(IObject*)
.– dfri
1 hour ago
1
1
@dfri THX for adding this information.
– πάντα ῥεῖ
1 hour ago
@dfri THX for adding this information.
– πάντα ῥεῖ
1 hour ago
|
show 1 more comment
@πάντα ῥεῖ'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
will mean
ObservableNode();node->notifyObservers(obj)
will invoke
Node::notifyObservers(IObject*)
and not
SingleObservable::notifyObservers(IObject*)
, which might be
unexpected, considering we instantiate anObservableNode
object
which specifies usingSingleObservable::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.
add a comment |
@πάντα ῥεῖ'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
will mean
ObservableNode();node->notifyObservers(obj)
will invoke
Node::notifyObservers(IObject*)
and not
SingleObservable::notifyObservers(IObject*)
, which might be
unexpected, considering we instantiate anObservableNode
object
which specifies usingSingleObservable::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.
add a comment |
@πάντα ῥεῖ'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
will mean
ObservableNode();node->notifyObservers(obj)
will invoke
Node::notifyObservers(IObject*)
and not
SingleObservable::notifyObservers(IObject*)
, which might be
unexpected, considering we instantiate anObservableNode
object
which specifies usingSingleObservable::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.
@πάντα ῥεῖ'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
will mean
ObservableNode();node->notifyObservers(obj)
will invoke
Node::notifyObservers(IObject*)
and not
SingleObservable::notifyObservers(IObject*)
, which might be
unexpected, considering we instantiate anObservableNode
object
which specifies usingSingleObservable::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.
edited 8 mins ago
answered 42 mins ago
dfridfri
36.5k462103
36.5k462103
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55890369%2fhow-to-delegate-to-implementing-class%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown