Figuring out the class of an inheriting object - c++

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.

Related

Automatically downcast function arguments in C++

I have two classes, let's say Base and Derived:
class Base {
public:
virtual ~Base() = 0;
};
class Derived : public Base {};
and a function foo:
auto foo (Derived* d) {
...
}
Is it possible to automatically downcast its argument? So I could do something like this:
Base* b = new Derived();
foo(b);
Basically I would like to write this without explicit casting it before function call.
I read something about conversion operators/constructors but they seem not useful in my case, do you have any other idea?
Edit: Sorry, I oversimplified the question with 2 classes and just a function. But actually I've got a library of 50-ish functions and 3 classes (a superclass and 2 subclasses). This unfortunately makes the easiest and cleanest solutions unsuitable because in my opinion (correct me if I am wrong) they scale bad.
I can think of three possible solutions, depending on your needs. I've replaced raw pointers with unique_ptrs in my examples.
Case 1: You don't need the base type of each derived type to be the same.
Use CRTP to allow the base type to invoke itself as a derived type. Example implementation:
template <typename DerivedType>
class Base {
template <typename F>
auto invoke_as_derived(F&& f) {
return std::forward<F>(f)(static_cast<DerivedType*>(this));
}
};
class Derived : public Base<DerivedType> {};
Usage:
std::unique_ptr<Base<Derived>> b = std::make_unique<Derived>();
b->invoke_as_derived(foo);
Since you mentioned using a list of Base pointers, this probably won't work for you.
Case 2: You need a shared base type but only have one layer in your type hierarchy and no virtual methods.
Use std::variant and std::visit.
class Derived {};
using Base = std::variant<Derived, /* other derived types */>;
auto foo(Derived*) { ... }
class FooCaller {
operator ()(Derived& d) {
return foo(&d);
}
// Overload for each derived type.
}
Usage:
Base b = Derived();
std::visit(FooCaller{}, b);
Case 3: You need a single base type but also want virtual methods and/or additional layers in your type hierarchy.
You might try the visitor pattern. It takes some boilerplate, but it may be the best solution depending on your needs. Sketch of the implementation:
class Visitor; // Forward declare visitor.
class Base
{
public:
virtual void accept(Visitor& v) = 0;
};
class Derived : public Base
{
public:
void accept(Visitor& v) final { v.visit(*this); }
};
struct Visitor
{
virtual void visit(Derived&) = 0;
// One visit method per derived type...
};
struct FooCaller : public Visitor
{
// Store return value of call to foo in a class member.
decltype(foo(new Derived())) return_value;
virtual void visit(Derived& d)
{
return_value = foo(&d);
}
// Override other methods...
};
Usage:
std::unique_ptr<Base> b = std::make_unique<Derived>();
FooCaller foo_caller;
b->accept(foo_caller);
You could write a visitor that takes a function to apply to the element so you don't have to repeat this for all of your many functions. Alternatively, if you can alter the functions themselves, you could replace your functions with visitor types.
Edit: Simplifying the call syntax back down to foo(b)
Define an overload per function overload set to which you want to pass Base objects. Example, using the 3rd technique:
auto foo(Base* b) {
FooCaller foo_caller;
b->accept(foo_caller);
return std::move(foo_caller.return_value);
}
Now foo(b.get()) will delegate to the appropriate overload of foo at run-time.
The usual approach would not be to downcast, but to use virtual functions. I.e. put void foo() inside of the class.
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() { std::cout << "Base foo()\n"; }
};
class Derived : public Base {
public:
void foo() override { std::cout << "Derived foo()\n"; }
};
int main()
{
Base* b = new Derived();
b->foo();
delete b;
}
outputs:
Derived foo()
If you want to make it impossible to call Base::foo(), you can set
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
making Base an abstract class.
But if you really want to call foo(b), you can use a (templated) helper function. E.g.:
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
class Derived : public Base {
public:
void foo() override {
std::cout << "Derived foo()\n";
}
};
template<typename T>
void foo(T* t)
{
t->foo();
}
int main()
{
Base* b = new Derived();
foo(b);
delete b;
}

calling parent function on a specific function call of every child C++

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 )

Is it possible to create an instance of a class within the same class?

Say I have a class:
class Foo{
public:
Foo(){
}
//Is it possible to create a function like this:
virtual Foo* createOb(){
//Should create a new Foo,Bar or Fiz, depending on the actual object type.
}
}
class Bar: public Foo{
public:
Bar(){
}
}
class Fiz: public Foo{
public:
Fiz(){
}
}
Is it possible to have a method createOb() in the base class, so when createOb() is called on an instance of one of the derived classes, that an instance of the derived class is created ?
Yes, it can be done, using CRTP.
Bu first, returning a raw pointer obtained from new is very dangerous. In c++ raw pointers should be used only when they do not have ownership of the pointed object. So I took the liberty to use unique_ptr:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base>
{
return std::unique_ptr<Base>{};
}
};
// abstract works too:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base> = 0;
};
template <class Derived>
struct Base_crtp : Base {
auto create_obj() -> std::unique_ptr<Base> override /* final */
{
return std::unique_ptr<Base>{new Derived{}};
}
};
struct D1 : Base_crtp<D1>
{
};
struct D2 : Base_crtp<D2>
{
};
And then:
auto b1 = std::unique_ptr<Base>{new D1{}};
auto b2 = std::unique_ptr<Base>{new D2{}};
auto new_d1 = b1->create_obj();
auto new_d2 = b2->create_obj();
Definitely YES!!!
When a method is declared virtual in base class, and called through the derived class object, then the derived class function gets called (Read vprt, vtable concept in c++).
#include <iostream>
using namespace std;
class A{
public:
virtual A* getobj(){
return new A();
}
};
class B: public A{
public:
B(){cout<<"B constructor"<<endl;}
virtual A* getobj(){
return new B();
}
};
int main()
{
A *a = new B();
A *second = a->getobj();
return 0;
}
In the above code, we are calling the getobj() function using class B's object.
Here the constructor of class B is called twice.
first, for new B() in main
secondly for getobj function call which again creates object of B
This is not an optimal solution, but it works.
In your .h
class Foo{
public:
Foo();
virtual Foo* createOb();
};
class Bar: public Foo{
public:
Bar();
};
class Fiz: public Foo{
public:
Fiz();
};
In your .cpp
#include "Header.h"
Foo::Foo() {}
Foo* Foo::createOb(){
if (dynamic_cast<Bar*>(this)) {
return new Bar();
}
else if (dynamic_cast<Foo*>(this)) {
return new Foo();
}
return nullptr;
}
Bar::Bar() {}
Fiz::Fiz() {}
As already suggested please consider a pure virtual method
No, this is not possible with "pure" inheritance. The classes must override createOb() member function in order to support cloning.
You can see why this is not possible by considering separate compilation of classes. An implementation of one-fits-all createOb() member function must be completed in isolation from Bar and Fiz, making it impossible for the base to know the type of its subclasses.
An implementation with a pure virtual function in the base is very common, though.
Another approach is to use Curiously Recurring Template Pattern (CRTP) to implement cloning. This article explains how it can be done.

base class pointer, invoke method based on derived type

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.

C++ is it possible to make a class extend one class and be a realization of an interface at the same time?

Coluld you provide a simple code example? (sorry C++ nube) and how to call a function from the class you are extending?
A bit useful example: :-)
class CImplementation
{
public:
void doFoo();
};
void CImplementation::doFoo()
{
//implementation
}
class IInterface
{
public:
virtual void foo()=0;
};
class DerivedFromImplementationAndInterface : public CImplementation, public IInterface
{
virtual void foo();
};
void DerivedFromImplementationAndInterface::foo()
{
doFoo();
}
//possible usage:
void method(IInterface& aInterface)
{
aInterface.foo();
}
void test()
{
IInterface* d = new DerivedFromImplementationAndInterface;
method(*d);
}
In C++, you can extend multiple classes, it's called multiple inheritance. Most probably this is what you're looking for. Please read a good book about multiple inheritance and C++ (a quick introduction: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr134.htm), because there are many pitfalls and details to pay attention to.
Example for multiple inheritance:
class A { ... };
class B { ... };
class C: public A, public B {}; // C inherits from A and B.
C++ doesn't explicitly have interfaces, the equivalent of an interface in Java is usually implemented with a class having only pure virtual functions (plus constructors, destructor, copy assignment):
#include <iostream>
// interface
class Fooable {
public:
virtual int foo() = 0;
virtual ~Fooable() {}
};
// base class
class Base {
public:
void non_virtual_function() { std::cout << "Base::non_virtual_function\n"; }
virtual void virtual_function() { std::cout << "Base::virtual_function\n"; }
};
// derived class, inherits from both Base "class" and Fooable "interface"
class Derived: public Base, public Fooable {
public:
virtual int foo() {
// call base class function
Base::non_virtual_function();
// virtual call to function defined in base class, overridden here
virtual_function();
}
virtual void virtual_function() {
// call base class implementation of virtual function directly (rare)
Base::virtual_function();
std::cout << "Derived::virtual_function\n";
}
void non_virtual_function() {
// not called
std::cout << "Derived::non_virtual_function\n";
}
};
int main() {
Derived d;
d.foo();
}
Not sure what you're asking:
class A
{
public:
void method();
};
class B
{
public:
void method();
};
class C : public A, public B
{
public:
void callingMethod();
};
void C::callingMethod()
{
// Here you can just call A::method() or B::method() directly.
A::method();
B::method();
}
Note that multiple inheritance can lead to really hard-to-solve problems and I would recommend to only use it when necessary.
The question as stated,
C++ is it possible to make a class extend one class and implement another?
does not make much sense. The answer to that is just "yes". You can derive from any number of classes: C++ fully support multiple inheritance.
So, given that the question as stated isn't really meaningful, it's at least possible that you meant to ask
C++ is it possible to make a class extend one class and thereby implement another?
The answer to this question is also yes, but it's not trivial. It involves virtual inheritance. Which is quite tricky.
Here's an example:
#include <iostream>
void say( char const s[] ) { std::cout << s << std::endl; }
class TalkerInterface
{
public:
virtual void saySomething() const = 0;
};
class TalkerImpl
: public virtual TalkerInterface
{
public:
void saySomething() const
{
say( "TalkerImpl!" );
}
};
class MyAbstractClass
: public virtual TalkerInterface
{
public:
void foo() const { saySomething(); }
};
class MyClass
: public MyAbstractClass
, public TalkerImpl
{};
int main()
{
MyClass().foo();
}
The virtual inheritance ensures that there is only one sub-object of type TalkerInterface in a MyClass instance. This has some counter-intuitive consequences. One is that "inheriting in an implementation" works, and another is that construction of that base class sub-object happens down in each MyClass constructor, and more generally down in the most derived class.
Cheers & hth.,