I am having some problems with automatic typecasting between shared_ptr of inherited classes.
My class structure is as follows, a base class Base and two derived classes Derived1 and Derived2.
// Base class
class Base {
protected:
...
...
public:
Base() = default;
virtual ~Base() = default;
virtual void run() = 0;
...
...
};
// Derived class
class Derived1: Base {
protected:
...
...
public:
Derived1() = default;
virtual ~Derived1() = default;
void run() {...}
...
...
};
// Derived class
class Derived2: Base {
protected:
...
...
public:
Derived2() = default;
virtual ~Derived2() = default;
void run() {...}
...
...
};
I have a function doSomething()
void doSomething(std::shared_ptr<Base> ptr) {
ptr->run();
...
}
I call the function with the derived classes like so -
doSomething(make_shared<Derived1>())
doSomething(make_shared<Derived2>())
But I get an error saying -
no viable conversion from 'shared_ptr<class Derived1>' to 'shared_ptr<class Base>'
no viable conversion from 'shared_ptr<class Derived1>' to 'shared_ptr<class Base>'
What am I doing wrong? Is it safe just to use static_pointer_cast to the Base type? Like -
doSomething(static_pointer_cast<Base>(make_sahred<Derived2>()))
SOLUTION
My bad... The problem was that I was inheriting the base class privately.
As far as I can tell, the code that you've presented compiles fine: http://ideone.com/06RB2W
#include <memory>
class Base {
public:
Base() = default;
virtual ~Base() = default;
virtual void run() = 0;
};
class Derived1: public Base {
public:
Derived1() = default;
virtual ~Derived1() = default;
void run() {}
};
class Derived2: public Base {
public:
Derived2() = default;
virtual ~Derived2() = default;
void run() {}
};
void doSomething(std::shared_ptr<Base> ptr) {
ptr->run();
}
int main() {
doSomething(std::make_shared<Derived1>());
doSomething(std::make_shared<Derived2>());
}
Related
I have a an interface:
/*base.hpp */
class Base {
protected:
Base() = default;
public:
Base(Base const &) = delete;
Base &operator=(Base const &) = delete;
Base(Base &&) = delete;
Base &operator=(Base &&) = delete;
virtual ~Base() = default;
virtual void Function1() = 0;
};
Also there is a function in this interface:
std::shared_ptr<Base> **getBase**(); //this will return the instance of Base class
Since function in base class is pure virtual, sample Derived class is below:
#inclide "base.hpp"
class Derived : public Base
{
public:
Derived();
~Derived();
virtual void Function1() override;
};
In main.cpp -> there is a call to getBase()
std::shared_ptr<Base> ptr{ nullptr };
void gettheproxy() {
ptr = getBase(); //call to get baseclass instance
}
Implementation of getBase method (in separate file getBase.cpp)
#include "base.hpp"
#include "derived.hpp"
Derived d;
std::shared_ptr<Base> getBase()
{
std::shared_ptr<Base> *b= &d;
return b;
}
Error:
cannot convert ‘Base*’ to Base’ in initialization
What is the correct way to get base class instance from derived class implementation?
Note: I have to follow this design of classes due to code dependency.
This should do:
std::shared_ptr<Derived> d = std::make_shared<Derived>();
std::shared_ptr<Base> getBase() { return d; }
If i have a base class Base:
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
};
And two derived classes:
class Derived1 : public Base
{
Derived1();
bool bar() override;
}
class Derived2 : public Base
{
Derived2();
std::vector<baz*> bazVector;
bool bar() override;
}
And i have a vector std::vector<Base*> mainVector which us populated like this:
mainVector.push_back(someDerivedPointer)
At some point i need to determine what object is stored: Derived1 or Derived2, so i could access Derived2->bazVector if object is Derived2
One solution is trying to dynamic_cast<Derived2>(mainVector.at(someIndex)) and check for returned nullptr, or storing some enum that would tell me what class this object belongs to, but these solutions seem crutchy, and i wonder if there is a better solution.
As advised in the comment section, you are probably looking the wrong direction.
There's high chance you are not tackling the problem with the right approach.
If you need to write different logic based on the actual derived class from a pointer, you are missing something.
We don't have too much details, but for what you said, you have two options:
1: adding a virtual method to retrieve your vector:
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
virtual std::vector<baz*> getVector() = 0;
};
class Derived1 : public Base
{
public:
Derived1();
bool bar() override;
virtual std::vector<baz*> getVector() override {return {};};
}
class Derived2 : public Base
{
std::vector<baz*> bazVector;
public:
Derived2();
bool bar() override;
virtual std::vector<baz*> getVector() override {return bazVector;};
}
2: insert the logic where you need this vector into a virtual function (this is probably the better):
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
virtual void doSomething() = 0;
};
class Derived1 : public Base
{
public:
Derived1();
bool bar() override;
virtual void doSomething() override {/*no op*/};
}
class Derived2 : public Base
{
std::vector<baz*> bazVector;
public:
Derived2();
bool bar() override;
virtual void doSomething() override {/*do something with you bazVector*/};
}
The other answer is most likely the best way to go forward in OP's case, but considering how vague the question's title is, there is an alternative idiom that is sometimes useful when:
All the derived classes of Base are known ahead of time.
The derived classes are particularly heterogenous, and creating a lowest-common-denominator interface would be problematic in some way, shape, or form.
A good example of this would be an AST. clang's ASTConsumer uses a flavor of the technique.
The visitor. The basic idea is to have an external interface with virtual methods for each derived class, and have a single virtual function in Base that dispatches this to the correct function.
class Derived1;
class Derived2;
class Base {
public:
class Visitor {
public:
virtual void operator()(Derived1&) {}
virtual void operator()(Derived2&) {}
protected:
~Visitor() = default;
};
virtual void visit(Visitor& v) = 0;
virtual ~Base() = default;
};
class Derived1 : public Base
{
public:
Derived1(){}
void visit(Base::Visitor& v) override { v(*this); }
};
class Derived2 : public Base
{
public:
Derived2(){}
void visit(Base::Visitor& v) override { v(*this); }
};
// Usage example:
struct MyVisitor final : public Base::Visitor {
void operator()(Derived1& obj) override {
std::cout << "1\n";
}
void operator()(Derived2& obj) override {
std::cout << "2\n";
}
};
int main() {
std::vector<std::unique_ptr<Base>> bases;
bases.push_back(std::make_unique<Derived1>());
bases.push_back(std::make_unique<Derived2>());
MyVisitor v;
for(auto& b : bases) {
b->visit(v);
}
}
#include <iostream>
#include <memory>
#include <cstdlib>
class IBase
{
public:
IBase() = default;
virtual ~IBase() = default;
virtual void f1() = 0;
};
class IDerived
{
public:
IDerived() = default;
virtual ~IDerived() = default;
virtual void f2() = 0;
};
class BaseImpl : public IBase
{
public:
BaseImpl() = default;
virtual ~BaseImpl() override = default;
virtual void f1() override { /* serious code */}
};
class DerivedImpl : public BaseImpl, public IDerived
{
public:
DerivedImpl() = default;
virtual ~DerivedImpl() override = default;
virtual void f2() override { /* serious code */}
};
class Base : public IBase
{
public:
Base() : m_impl(std::make_shared<BaseImpl>()) {}
virtual ~Base() override = default;
virtual void f1() override { m_impl->f1(); }
protected:
Base(const std::shared_ptr<BaseImpl>& impl) : m_impl(impl) {}
std::shared_ptr<BaseImpl> m_impl;
};
class Derived : public Base, public IDerived
{
public:
Derived() : Base(std::make_shared<DerivedImpl>()) {}
virtual ~Derived() override = default;
virtual void f2() override { impl()->f2(); }
private:
std::shared_ptr<DerivedImpl> impl() { return std::dynamic_pointer_cast<DerivedImpl>(m_impl); }
};
int main()
{
Base base;
base.f1();
Derived derived;
derived.f1();
derived.f2();
std::cin.sync();
std::cin.get();
return EXIT_SUCCESS;
}
It works, but it looks so weird that I might just give up pimpl.
Imagine having your Base defined like this:
class Base {
public:
Base();
virtual ~Base();
virtual void f1();
protected:
class Impl;
Impl *p_impl; // or shared_ptr, or unique_ptr, or whatever you like.
};
Note that there is nothing defined of Base::Impl. This is a very important part of the PIMPL idiom as you might have to use elements in the Impl class that require #include-ing things you don't want to include in the header class.
The derived class would then look like this:
class Derived: public Base {
public:
Derived();
~Derived();
virtual void f1(); // or not, depends
virtual void f2();
protected:
class Impl2;
Impl2 *p_impl2; // note that Derived::Impl2 might inherit from Base::Impl
};
This still hides the implementation details of both Base and Derived in Base::Impl and Derived::Impl2, while giving you complete freedom to implement Derived in any way you like (including inheritance).
Your Impl classes should only contain private variables and methods.
Don't put anything that that need to be accessible from children class there. Sub-classing the Impl class is wrong way to go in C++ because that defeats the purpose of this pattern.
Let's say the scenario is this.
IBase - interface.
BaseImpl - implementation.
BaseStub - allocates std::unique_ptr to BaseImpl named m_impl.
And then how to achieve the following?
IDerived - interface.
DerivedImpl - implementation, inherits from BaseImpl.
DerivedStub - allocates std::unique_ptr to DerivedImpl named m_impl, inherits from BaseStub.
It becomes a problem that BaseStub already allocates its implementation, and since DerivedStub does the same, it conflicts.
class IBase
{
public:
virtual void f1() = 0;
};
class IDerived
{
public:
virtual void f2() = 0;
};
class BaseImpl : public IBase
{
public:
virtual void f1() override {}
};
class DerivedImpl : public BaseImpl, public IDerived
{
public:
virtual void f2() override {}
};
class BaseStub : public IBase
{
public:
BaseStub() { m_impl.reset(new BaseImpl()); }
virtual void f1() override { m_impl->f1(); }
private:
std::unique_ptr<BaseImpl> m_impl;
};
// But this also creates BaseStub::m_impl.
class DerivedStub : public BaseStub, public IDerived
{
public:
DerivedStub() { m_impl.reset(new DerivedImpl()); }
virtual void f2() override { m_impl->f2(); }
private:
std::unique_ptr<DerivedImpl> m_impl;
};
Can I have a base class with a member that is an instance of a derived class? How should I forward-declare or include the derived class definition? Or is there another way altogether that I should be doing this?
// base.h
class DerivedClass; // Is forward declaration sufficient?
class Base {
public:
virtual ~Base();
virtual void DoStuff() = 0;
void DoSomethingWithD() {
d_.Foo();
}
protected:
DerivedClass d_;
};
// derived.h
#include "base.h"
class Derived : public Base {
public:
Derived();
void DoStuff();
void Foo();
private:
Derived(const Derived&);
void operator=(const Derived&);
};
// other_derived.h
#include "base.h"
class OtherDerived : public Base {
public:
OtherDerived();
void DoStuff();
private:
OtherDerived(const OtherDerived&);
void operator=(const OtherDerived&);
};
This will work for you, see comments on changes:
#include <memory>
class Derived;
class Base {
public:
virtual ~Base();
virtual void DoStuff() = 0;
void DoSomethingWithD(); // no longer defined in-line
protected:
std::unique_ptr<Derived> d_; // storing as a pointer as Derived is still incomplete
};
class Derived : public Base {
public:
Derived();
void DoStuff();
void Foo();
private:
Derived(const Derived&);
void operator=(const Derived&);
};
class OtherDerived : public Base {
public:
OtherDerived();
void DoStuff();
private:
OtherDerived(const OtherDerived&);
void operator=(const OtherDerived&);
};
// definition moved down here where Derived is a complete type
void Base::DoSomethingWithD() {
d_->Foo();
}