Given:
class Foo {
public:
void Method1();
}
class Bar extends Foo {
public:
Bar* Method2();
}
class Baz extends Bar {
public:
Baz* Method3();
}
So,
someObject *b = new Baz();
b->Method3()->Method2()->Method1();
This will work, as Baz() contains all methods including Method2(), Bar contains Method1();
But, due to return type this seems to be a bad idea - when accessing simpler Method1() at first inheritance level before calling more complex Method3(), and having to keep this calls in single line..
b->Method1()->Method2()->Method(3); // will not work?
Also, someone told me that putting try.. catch.. throw inside one of those Method's will occasionally exit the chain without calling next method at wrong value. Is this true?
So how to properly implement method chaining in C++?
That's what virtual methods are for. From the syntax errors I gather that you are new to C++
struct Base
{
virtual Base* One() { return this; };
void TemplateMethod() { this->One(); }
};
struct Derived : public Base
{
virtual Base* One() { /* do something */ return Base::One(); }
};
When you call TemplateMethod:
int main()
{
Base* d = new Derived();
d->TemplateMethod(); // *will* call Derived::One() because it's virtual
delete d;
return 0;
}
Related
So assume there is class A with function foo.
Class A is the parent of a few classes which all have the function foo.
All of the child classes need the functionality of
A::foo and adds upon it.
For example:
class A
{
public:
void foo()
{
print('A');
}
};
class B:public A
{
public:
void foo()
{
print("B");
}
};
class C:public A
{
public:
void foo()
{
print("C");
}
};
void main()
{
B b;
C c;
c.foo()// now only goes to C::foo(), meaning print C. I want it to to also go into A::foo() meaning print AC
b.foo()//now only goes to B::foo(),meaning print B. want it to print AB
}
And if I want to add class D : A with foo function it will also do A::foo() and then D::foo()
Sorry if I am missing something obvious.
EDIT : since it wasn't clear the question was if there is an automatic way to do so.
EDIT : found a workaround:
class A
{
virtual void foo2(){}
public:
void foo()
{
print('A');
foo2();
}
};
class B:public A
{
void foo2()
{
print("B");
}
public:
};
class C:public A
{
void foo2()
{
print("C");
}
public:
};
void main()
{
B b;
C c;
c.foo()// now prints AC
b.foo()//now prints AB
}
seems redundant since now there are 2 functions now.
You can call the parent class's implementation of a function using A::foo().
In your case, simply adding that function call will achieve the result you want:
class B:public A
{
public:
void foo()
{
A::foo();
print("B");
}
};
As a side note, whenever you intend to override functions, you should declare it as virtual:
class A
{
public:
virtual void foo()
{
print('A');
}
};
And then when overriding it, use the override keyword:
class B:public A
{
public:
void foo() override
{
print("B");
}
};
What you've called a workaround is an established solution to this question, and whilst some people might call it a workaround many wouldn't.
Its even got a name that covers it. The non-virtual interface pattern.
herb sutter :- http://www.gotw.ca/publications/mill18.htm
One example from S.O., there's probably more:-
Non-virtual interface design pattern in C#/C++
I'd argue that this IS a way to do it automatically.
As to your aside that its redundant because there are 2 functions - well there were 2 before (the base version and derived version).
One benefit of this approach in some designs is that if the virtual method foo2 is pure virtual (which would make A abstract) then this forces all immediate derived classes to implement foo2. (I say immediate because if B derives from A it must implement foo2 but if C then derives from B C isn't forced to implement foo2, it has access to B::foo2 )
I understand that the following code doesn't work -- can't convert base to foo.
Is there something I can do, or some pattern to employ which would get me close the behavior I'm trying to achieve in the code below? IOW, if I have a base class pointer to a derived type, how can I invoke a specific method that matches the derived type (not the base type)?
What patterns might I use? I looked into Curiously Recursive (or recurring) Template Pattern, however this imposed other limitations itself.
class base {};
class foo : public base {};
void method(const foo& f){}
int main(){
base* b = new foo();
method(*b);
}
The easiest way is probably to just make method() a virtual member function on foo:
class base {
public:
virtual void method() const = 0;
};
class foo : public base {
public:
void method() const override { }
};
int main(){
foo f;
base* b = &f;
b->method();
}
But if for some reason that is not possible (perhaps you don't have access to method() or perhaps you want to keep the logic in method() separate from foo) you could use a simplified version of the Visitor Pattern.
The visitor pattern relies on all the classes in your hierarchy having a virtual function to dispatch based on class type.
In your case you don't need double-dispatch so you don't actually need the visitor object and can just call your method function directly from a virtual dispatch function:
class base {
public:
virtual void dispatch() const = 0;
};
class foo : public base {
public:
void dispatch() const override;
};
void method(const foo& f){}
void foo::dispatch() const {
method(*this);
}
int main(){
foo f;
base* b = &f;
b->dispatch();
}
You have to remember that in most contexts the compiler doesn't know that your base pointer is actually of type foo.
Use virtual functions to solve these kinds of problems:
class base {
public:
virtual void func() const { /* A */ }
};
class foo : public base {
public:
void func() const override { /* B */ }
};
void method(const base& f) {
f.func();
}
int main(){
base* b = new foo();
method(*b);
}
Now, depending on the actual type of f, either A or B code will be executed in method.
I have a inheritance that the destructor of base class applies Template Method Pattern. The destructor has to do some works before calling the virtual clean function, and do some another works after calling.
We know that Never Call Virtual Functions during Construction or Destruction. So the following code definitely is not available.
class base
{
public:
virtual ~base()
{
// ... do something before do_clear()
do_clear();
// ... do something after do_clear()
}
private:
virtual void do_clear() = 0;
};
class d1
: public base
{
public:
d1() : m_x(new int) {}
~d1() {}
private:
virtual void do_clear()
{
delete m_x;
}
int *m_x;
};
But if I moved the destruction of process to the destructor of derived class, for example:
class base
{
public:
virtual ~base()
{
}
protected:
void clear()
{
// ... do something before do_clear()
do_clear();
// ... do something after do_clear()
}
private:
virtual void do_clear() = 0;
};
class d1
: public base
{
public:
d1() : m_x(new int) {}
~d1()
{
clear();
}
private:
virtual void do_clear()
{
delete m_x;
}
int *m_x;
};
If the client write that:
base *x = new d1;
delete x;
It will call ~d1(), then call base::clear(), eventually call the virtual function d1::do_clear() properly.
The base::clear() can been moved to public, and the client can make things safely by calling base::clear() before destruction. A precondition is the client must know and not forget to call, I think it isn't convenient and breaks encapsulation.
My question is:
Is the design dangerous/risk?
Is existing other better design for this?
There are two problems with your current design. The first is that it violates the rule of five/rule of zero. This means that ordinary usage of these classes is almost certain to result in memory leaks or double deletions.
The second problem is that you are using inheritance to model something that is probably better modelled with composition. base wants d1 to provide some extra functionality to its destructor, with the exact form of this functionality specified at run-time. The use of a replaceable interface is therefore internal to base, and so should not be externally visible.
Here is how I would write this code (using wheels::value_ptr):
struct D_interface {
//Providing virtual functions for run-time modifiable behaviour
virtual D_interface *clone() const = 0;
virtual ~D_interface(){}
};
struct D_Delete {
//Here is the code to call through to the virtual `D` object behaviour:
void operator()(D_interface *p) {
// ... do something before delete p;
delete p;
// ... do something after delete p;
}
//Put (pointers to) relevant data here,
//initialise them when constructing the `value_ptr`, or
//at a later stage with get_deleter
};
struct d1 : D_interface {
wheels::value_ptr<int> mx;
virtual D_interface *clone() const {
return new d1(*this);
}
};
//Nothing derives from `base`, because the polymorphism that is needed is internal
//to the implementation of `base`
//To add new functionality, add a new `D_interface` implementation.
class base
{
wheels::value_ptr<D_interface, wheels::DefaultCloner<D_interface>, D_Delete> D_impl;
public:
base(D_interface *D_impl)
: D_impl(D_impl)
{
}
};
For my part I think that this pattern it is sure because you need to implement the virtual function in the derived classes. This is the philosophy of virtual classes.
I have some troubles understanding how to manage the access rights of virtual methods. I made two small code samples, but I can't understand how things work.
Code Sample 1
The first code contains 3 classes: a mother class Foo and two derived classes. The class Baz looks a little bit like a Composite. There's a virtual method, but it's protected.
class Foo
{
protected:
virtual void doIt() = 0;
};
class Bar : public Foo
{
protected:
void doIt()
{}
};
class Baz : public Foo
{
protected:
void doIt()
{
M_foo->doIt(); // Error here
}
private:
Foo* M_foo;
};
When trying to compile (Visual C++ 2010) this, I get an error: I can't call doIt from a pointer to Foo in the derived class. So, my understanding was "I can't call this method because it could actually call another one (e.g. the one of Bar) to which I have no right".
Code Sample 2
I decided to change a bit the design of the code and design a function instead of the virtual method. However, to access a protected method, I need to add friendship with my function.
class Foo
{
friend void doItPlease( Foo* foo);
protected:
virtual Foo* getChild() = 0;
};
class Bar : public Foo
{
protected:
Foo* getChild()
{ return 0;}
};
class Baz : public Foo
{
protected:
Foo* getChild()
{
return M_foo;
}
private:
Foo* M_foo;
};
void doItPlease( Foo* foo)
{
Foo* myFoo( foo->getChild() );
};
This code compiles fine. The problem is that I can't understand why: I have declared only the base class as friend, not the children classes and friendship is not inherited. But now, when I call getChild from the function, it is like I would call a method to which I have no right (the one in Baz e.g.).
Could someone explain me how are the rights related to virtual methods managed?
Those are the rules for protected. They allow access to the base class subobject, but not for any unrelated instances like yours.
If you google for protected, you will find advice to avoid it in the first place, use private and public only, the intermediate is quite rarely good.
The point is that you define privateness from base class' perspective. If some action is allowed from the outside, it's irrelevant that the unknown party is freestanding or happens to be a subclass. The only relevant attribute is it's being known to be trusted or not.
If the particular derived class is defined along with base, feel free to make it friend, just keep maintaining the rules.
class Foo
{
public:
friend class Baz;
protected:
virtual void doIt() = 0;
};
class Baz : public Foo
{
public:
Baz(Foo* foo)
: M_foo(foo)
{
}
protected:
void doIt()
{
M_foo->doIt();
}
private:
Foo* M_foo;
};
This could not work beacause Foo::doIt is an undifined virtual method method
class Baz : public Foo
{
protected:
void doIt()
{
Foo::doIt();
}
};
But if you have something like this it's should work fine
class Baz : public Foo
{
Baz()
{
M_foo = new Bar();
}
protected:
void doIt()
{
M_foo->doIt();
}
private:
Foo* M_foo;
};
I have a linked list of Foo objects. Foo is a base class, which has several classes inherit from it. Say, classes A, B, and C.
I am cycling through this linked list and calling a method some_method, which has 3 definitions; one for each child class:
some_method(A a);
some_method(B b);
some_method(C c);
The linked list is generic, so it is of type Foo, as it has an assortment of A, B and C objects.
When I'm cycling through the linked list at current_element, calling some_method(current_element);, how can I make it call the right method? The compiler complained until I wrote a some_method that took the generic Foo, and it only calls into that method.
Depending on your requirements, you may want to consider using polymorphism. To do this, add a pure virtual method to your base node class, and move the corresponding methods to the derived classes.
class Foo
{
public:
virtual void some_method() = 0;
};
class A : Foo
{
public
virtual void some_method()
{
// move the body of some_method(A a) here
}
};
For this to work, your linked list will need Foo*, instead of Foo.
class Node
{
public:
Foo* foo;
Node* next;
};
// ...
Node* someNode = GetNode();
// Calls correct method - A::some_method, B::some_method, or C::some_method
someNode->foo->some_method();
If you can't put some_method in Foo/A/B/C, then you might want to look into the Visitor design pattern:
http://en.wikipedia.org/wiki/Visitor_pattern
This is the "double dispatch" problem. You can use the visitor pattern. Usually the Visitor is a base class so you can re-use this design for multiple problems.
#include <iostream>
class FooVisitor;
class Foo
{
public:
virtual void some_method() = 0;
virtual void visit(FooVisitor* v) = 0;
};
class A;
class B;
class FooVisitor
{
public:
virtual void visit(A* a){ std::cout << "A" << std::endl;}
virtual void visit(B* b){std::cout << "B" << std::endl;}
};
class A : public Foo
{
public:
virtual void some_method()
{
// move the body of some_method(A a) here
}
virtual void visit(FooVisitor* v) { v->visit(this);}
};
class B : public Foo
{
public:
virtual void some_method()
{
// move the body of some_method(A a) here
}
virtual void visit(FooVisitor* v) { v->visit(this);}
};
int main()
{
FooVisitor fv;
Foo* f1 = new A;
f1->visit(&fv);
Foo* f2 = new B;
f2->visit(&fv);
getchar();
}
Two ways:
1) the better way:
Reverse your design such that someMethod is a virtual method of the base class Foo and redefine it in the derived classes. As:
class Foo {
public:
virtual void someMethod() = 0;
};
class A {
public:
void someMethod() { /* implementation specific to A here */ };
};
class B {
public:
void someMethod() { /* implementation specific to B here */ };
};
class C {
public:
void someMethod() { /* implementation specific to C here */ };
};
Then calling the someMethod on a pointer to Foo will automatically call the method from the appropriate class. If that cannot be done because someMethod cannot be implemented as part of Foo or its derivatives (e.g. it needs access to private members of the class it is currently in in your design), then you might try to split this functionality apart into subproblems that can be put into virtual methods of these classes A B C.
2) the "I don't have a choice" way:
Use RTTI (Run-Time Type Identification), it is included in C++. It requires that your base class Foo has at least one virtual method. You need to #include <typeinfo>, then use typeid() on the pointer, it will return a type_info object, and you can compare its name() result with the class names A B and C. This isn't a very nice approach because it has more overhead and it breaks OOP design principles. But if that's the only option, it's fine.
RTTI is your friend here. The example given in the link will guide you further
You can call the method for the child class as a member method. For exampleA a = new A(); a.some_method() should call the correct the method. Within some_method() you can reference to object using keyword this.