Cast from Abstract Parent Class to Child Class - c++

I have this code,
class IFoo
{
public:
IFoo(){}
virtual ~IFoo(){}
virtual void fooFunc() = 0;
};
class Foo : public IFoo
{
public:
Foo(){}
virtual ~Foo(){}
virtual void fooFunc(){/*impl*/}
};
class Poop : public IFoo
{
public:
Poop(){}
virtual ~Poop(){}
virtual void fooFunc(){/*impl*/}
};
class Bar
{
public:
Bar(){}
~Bar(){}
void setFoo(Foo* foo){/*impl*/}
};
//in main
Poop* poop = new Poop;
Bar bar;
bar.setFoo(poop);
delete poop;
Compiling this code gives me an error message about invalid conversion. What kind of casting should I use for this?
Please advise. Many thanks!

Poop does not derive from Foo, so you cannot pass a Poop* where a Foo* is expected, and vice versa. Poop and Foo both derive from IFoo so you need to instead change setFoo() to accept an IFoo* instead of a Foo*:
void setFoo(IFoo* foo){/*impl*/}

Related

shared_ptr to derived class from a specific base class

I feel like this is a pretty basic C++ question. I am trying to make a class which contains a member variable which is a shared_ptr to any class which is derived from a specific interface, but does not care which particular derived class it is. I am implementing it as follows:
class Base
{
public:
Base();
virtual void do_stuff() = 0;
};
class Derived : Base {
Derived() {}
void do_stuff() { };
};
class Foo
{
public:
Foo() {
mPtr = std::make_shared<Derived>();
}
protected:
std::shared_ptr<Base> mPtr;
};
Compiling gives the following error at the top:
error: no match for ‘operator=’ (operand types are ‘std::shared_ptr<Base>’ and ‘std::shared_ptr<Derived>’)
mPtr = std::make_shared<Derived>();
What's the proper way to do this?
Edit: Changing inheritence from Base to public Base made it work. However, trying to instantiate the class makes the linker break.
Foo foo;
Compiling gives
libfoo.so: undefined reference to `Base::Base()'
collect2: error: ld returned 1 exit status
What's this about?
Fixed the access specifiers and more:
#include <memory>
class Base {
public:
Base() = default; // must have implementation
// virtual dtor - not strictly needed for shared_ptr:
virtual ~Base() = default;
virtual void do_stuff() = 0;
};
class Derived : public Base { // public inheritance
public: // public access
// Derived() {} // not needed
void do_stuff() override {}; // mark override
};
class Foo {
public:
Foo() :
mPtr{std::make_shared<Derived>()} // use the member init-list
{}
private: // prefer private member variables
std::shared_ptr<Base> mPtr;
};
Derived should use public inheritance, rather than private inheritance, and Derived() should be public.
class Derived : public Base
{
public:
Derived() {}
void do_stuff() override{ };
};

c++ abstract class implementation in another base class

Question
Why not to try virtual inheritance if it seems to solve my diamond inheritance problem below?
Briefing:
While learning C++, I came with some compiler errors for the following code:
#include <stdlib.h>
#include <iostream>
class IFoo{
public:
virtual void Hello() = 0;
};
class Foo : public IFoo{
public:
void Hello()
{
printf("Hello");
}
};
class IBar : public IFoo{
public:
virtual void HelloWorld() = 0;
};
class Bar : public IBar, public Foo{
public:
void HelloWorld()
{
Hello();
printf("World");
}
};
int main()
{
Bar b;
b.HelloWorld();
system("pause");
return 0;
}
I want Bar to implement abstract class IBar which has IFoo as a base class but then I want all the implementation of IFoo provided by Bar's second base class Foo.
I get 2 compiler errors (GCC 4.9.2): One related to ambiguities and another one about missing implementations for abstract class IFoo.
Then I found this question and got to meet the concept of virtual inheritance, which lead me to this page. Following the tutorial, I added virtual inheritance and all problems were gone:
class Foo : public virtual IFoo{...
class IBar : public virtual IFoo{...
But a user in the question suggest not to try virtual inheritance. Hence my question.
Your class
Bar
must override
Hello
otherwise class Bar also becomes purely abstract, because
Hello
is inherited all the way from
IFoo.
Whenever a class inherits an abtract base class it must implement all of the base class' pure virtual functions, otherwise the derived class itself also becomes abstract.
class Base{
public:
virtual void foo() = 0;
};
// this class is abstract, it doesn't implement Base::foo
class Derived1 : public Base{
public:
void fooDerived() {}
};
// this class is not abstract, it implements Base::foo
class Derived2 : public Base{
public:
void foo() {}
};
As suggested in another answer, in C++11 you can declare the function using the override keyword, which ensures that the function overrides a virtual function. Like this:
// this class is not abstract, it implements Base::foo
class Derived2 : public Base{
public:
void foo() override {}
};
Virtual inheritance solves another problem, the problem of ambiguity when inheriting from more than one base class which declares identical functions or members.
Your Hello() call in Bar::HelloWorld() is ambiguous. The compiler can't tell if you are trying to call Hello() from IBar or Foo. You can call Foo::Hello() or IBar::Hello() in it's place. That being said, your inheritance structure doesn't really make sense.
Your Bar class also needs to override Hello that it inherits from IBar.
If you have c++11, it would be a good idea to mark the virtual functions you are overriding with the override keyword:
#include <stdlib.h>
#include <iostream>
class IFoo{
public:
virtual void Hello() = 0;
};
class Foo : public IFoo{
public:
virtual void Hello() override
{
printf("Hello");
}
};
class IBar : public IFoo{
public:
virtual void HelloWorld() = 0;
};
class Bar : public IBar, public Foo{
public:
virtual void HelloWorld() override
{
Foo::Hello();
printf("World");
}
void Hello() override {}
};
int main()
{
Bar b;
b.HelloWorld();
system("pause");
return 0;
}
To answer your question on virtual inheritance, you could easily change your inheritance structure to something that still works that avoids a diamond pattern. The diamond pattern is rarely needed and is usually avoidable:
#include <stdlib.h>
#include <iostream>
class IFoo{
public:
virtual void Hello() = 0;
};
class Foo : public IFoo{
public:
virtual void Hello() override
{
printf("Hello");
}
};
class IBar {
public:
virtual void World() = 0;
};
class Bar : public IBar{
public:
virtual void World() override
{
printf("World");
}
};
class FooBar : public Foo, public Bar
{
public:
virtual void HelloWorld()
{
Hello();
World();
}
};
int main()
{
FooBar b;
b.HelloWorld();
system("pause");
return 0;
}

Implementing a class hierarchy properly

Say I have an interface hierarchy :
class A
{
virtual void commonFunc() = 0;
};
class B1 : public A
{
virtual void b1SpecificFunc() = 0;
};
class B2 : public A
{
virtual void b2SpecificFunc() = 0;
};
Interface A only exist to avoid duplicating the commonFunc() function.
Now if I want to implement this in order to have 2 instanciatable classes ImplB1 and ImplB2 i could do :
class ImplA
{
virtual void commonFunc();
};
class ImplB1 : public ImplA
{
virtual void b1SpecificFunc();
};
class ImplB2 : public ImplA
{
virtual void b2SpecificFunc();
};
The problem with this is that it makes ImplA instanciatable, which I don't want to. I only want ImplB1 and ImplB2 to be instanciatable, because ImplA is something asbtract that only exist to have the implementation of the common function in common.
How could i design this please ? Thank you.
Interface A only exist to avoid duplicating the commonFunc() function.
You certainly mean to avoid duplicating its declaration, don't you?
class ImplA
{
virtual void commonFunc();
};
This should probably be:
class ImplA : public A
{
virtual void commonFunc();
};
And I guess the point is that ImplA actually has an implementation of commonFunc. So for the sake of this answer's brevity, let's put it into the class definition:
class ImplA : public A
{
virtual void commonFunc() {} // implementation
};
The problem with this is that it makes ImplA instanciatable.
Just make ImplA's destructor pure virtual:
class ImplA : public A
{
public:
virtual ~ImplA() = 0 {}
private:
virtual void commonFunc() {}
};
This will prevent instantiation even inside of derived classes' functions. For example, the following will create a compiler error:
class ImplB1 : public ImplA
{
public:
virtual void b1SpecificFunc()
{
ImplA a; // error, cannot instantiate abstract class
}
};
In fact, you will not even be able to instantiate the class in its own functions:
class ImplA : public A
{
public:
virtual ~ImplA() = 0 {}
private:
virtual void commonFunc()
{
ImplA a; // error, cannot instantiate abstract class
}
};
But seriously, this all seems pretty over-engineered. Perhaps what you really need is to make commonFunc a non-virtual protected function of A, which derived classes can then call if they need to.
Or perhaps commonFunc can just be a free-standing utility function?
You can do the following. Also, here is a SO question/answer about this.
Note: While I'm answering the question that you can do this I'm not asserting it's what you should do.
Code
#include <iostream>
class A
{
public:
virtual void commonFunc() = 0;
};
void A::commonFunc() // Pure virtual but implemented anyway
{
// Derived classes can explicitly opt-in to this implementation
std::cout << "A::commonFunc()\n";
}
class B1 : public A
{
public:
virtual void b1SpecificFunc() = 0;
};
class B2 : public A
{
virtual void b2SpecificFunc() = 0;
};
class ImplB1 : public B1
{
public:
// This function must be implemented because its declared pure virtual
virtual void commonFunc()
{
// Can override the behavior if desired...
A::commonFunc(); // Explicitly use default implementation
}
virtual void b1SpecificFunc()
{
std::cout << "b1SpecificFunc()\n";
}
};
class ImplB2 : public B2
{
public:
// This function must be implemented because its declared pure virtual
virtual void commonFunc()
{
// Can override the behavior if desired...
A::commonFunc(); // Explicitly use default implementation
}
virtual void b2SpecificFunc()
{
std::cout << "b2SpecificFunc()\n";
}
};
int main()
{
//A a; // Won't compile (as expected/desired)
ImplB1 b1;
ImplB2 b2;
b1.commonFunc();
b1.b1SpecificFunc();
b2.commonFunc();
b2.b2SpecificFunc();
return 0;
}
Output
A::commonFunc()
b1SpecificFunc()
A::commonFunc()
b2SpecificFunc()

C++ polymorphism use child constructor

I want to use child class constructor when parent object was given to a function.
class foo {
public:
virtual void doThing() { };
};
class bar : public foo {
public:
void doThing() override;
};
class bar2 : public foo {
public:
void doThing() override;
};
int main () {
bar obj;
bar2 obj2;
someFunction(&obj);
someFunction(&obj2);
}
void someFunction(foo *obj) {
//child object construction
}
If bar class object pointer was passed to a someFunction() then it would create new bar object inside function. Same thing with bar2 class and so on.
My question: is there a way to construct a child object when object's reference was given?
The typical way you do this is to provide a pure virtual "clone" method in foo, and then define it in the members.
The particularly good designers (A good designer is a lazy designer) use the Curiously Recursing Template Pattern (CRTP) to help this out.
class foo { public: virtual foo* clone() const=0; virtual ~foo(){}}
template <typename Derived>
class foo_helper : public foo
{
public:
virtual foo* clone() const
{
return new Derived(static_cast<const Derived&>(*this));
}
virtual ~foo_helper(){}
}
class Bar : foo_helper<Bar>
{
public:
virtual ~Bar(){}
}
see also:
http://katyscode.wordpress.com/2013/08/22/c-polymorphic-cloning-and-the-crtp-curiously-recurring-template-pattern/

C++ virtual method: access rights, friends & Co

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;
};