I have a need to clone a derived class given only a reference or pointer to the base class. The following code does the job, but doesn't seem elegant, because I'm putting boilerplate code into many derived classes C, D, E that are siblings of B (not shown) that just calls the default copy constructor of each. Isn't that what the default copy constructor is for, if only it could be virtual?
Is there a better way?
Making a virtual assignment operator would be wrong, as I don't want C to assign to B, B to D, etc, just clone B, C, D or E.
#include <iostream>
using namespace std;
class A {
public:
virtual ~A() {}
virtual A* clone()=0;
};
class B : public A {
int i;
public:
virtual A* clone() {
cout << "cloned B" << endl;
return new B(*this);
}
virtual ~B() { cout << "destroyed b" << endl; }
};
int main() {
A* a = new B();
A* aa = a->clone();
delete a;
delete aa;
return 0;
}
You could always stick all the cloning logic into its own class in the middle of the hierarchy:
template <class Derived, class Base>
class CloneCRTP : public Base {
public:
Derived* clone() const override {
return new Derived(static_cast<Derived const&>(*this));
}
};
And then:
class B : public CloneCRTP<B, A>
{
int i;
public:
virtual ~B() { cout << "destroyed b" << endl; }
};
No more boilerplate.
You can rely on the CRTP idiom.
It follows a minimal, working example:
struct B {
~virtual ~B() { }
virtual B* clone() = 0;
};
template<class C>
struct D: public B {
B* clone() {
return new C{*static_cast<C*>(this)};
}
};
struct S: public D<S> { };
int main() {
B *b1 = new S;
B *b2 = b1->clone();
delete b1;
delete b2;
}
To achieve clone that works as with covariant return type, there is a need for some more complicated CRTP:
class Shape {
// virtual
virtual Shape* do_clone() const = 0;
public:
virtual ~Shape() {}
// non-virtual
Shape* clone() const {
return do_clone();
}
// ...
};
template <class Derived, class Base>
class CloneCRTP : public Base {
// virtual
Base* do_clone() const override {
return new Derived(static_cast<Derived const&>(*this));
}
public:
// non-virtual
Derived* clone() const {
return static_cast<Derived*>(do_clone());
}
};
Usage:
class Rectangle: public CloneCRTP<Rectangle, Shape> { /*...*/ };
class Triangle: public CloneCRTP<Triangle, Shape> { /*...*/ };
int main() {
Rectangle* r1 = new Rectangle{};
// getting the proper type from clone:
Rectangle* rcopy = r1->clone();
delete rcopy;
delete r1;
Triangle t1{};
// getting the proper type from clone:
Triangle* tcopy = t1.clone();
delete tcopy;
}
Code: http://coliru.stacked-crooked.com/a/339458f8b45299c3
I do it in a generalized way.
Definition:
template <class Class>
class CloneInterface {
public:
Class* copy() const { return new Class{static_cast<Class const&>(*this)}; }
virtual Class* clone() const { return this->copy(); }
};
template <class Derived, class Base>
class CloneCRTP : public Base {
public:
Derived* copy() const { return new Derived{static_cast<Derived const&>(*this)}; }
Base* clone() const override { return this->copy(); }
};
Usage:
class Base : public CloneInterface<Base> {
private:
int a = 0;
public:
virtual ~Base() {}
void print() { std::cout << "Base: a = " << a << '\n'; }
};
class A : public CloneCRTP<A, Base> {
private:
int b = 1;
public:
void print() { std::cout << "A: b = " << b << '\n'; }
};
Example:
int main() {
auto b = new Base();
auto b_clone = b->clone();
auto b_copy = b->copy();
b->print(); // Base print()
b_clone->print(); // Base print()
b_copy->print(); // Base print()
std::cout << "=========================\n";
auto a = new A();
auto a_clone = a->clone(); // returns Base*
auto a_copy = a->copy(); // returns A*
a->print(); // A print()
a_clone->print(); // Base print(), because clone returns pointer to the base class
a_copy->print(); // A print()
std::cout << "=========================\n";
auto c = static_cast<Base*>(a);
auto c_clone = c->clone(); // returns Base*, but A* inside
auto c_copy = c->copy(); // returns Base*, that is really Base
c->print(); // Base print()
c_clone->print(); // Base print()
c_copy->print(); // Base print()
std::cout << "=========================\n";
auto a_clone_restored = static_cast<A*>(c_clone);
auto a_copy_restored = static_cast<A*>(c_copy); // Invalid
a_clone_restored->print(); // A print()
a_copy_restored->print(); // A print()
delete b;
delete b_clone;
delete b_copy;
delete a;
delete a_clone;
delete a_copy;
return 0;
}
This approach allows to reuse crtp definition in all hierarchies that require clone functionality.
Code: https://coliru.stacked-crooked.com/a/269a2427fd2f919b
Related
In the virtual method create() in the derived class Derived, I return a struct of type HelpDerived. However, since I had to set the return type of the method to HelpBase, I found that I need to cast the returned object back to the type HelpDerived.
The following is an example of my case.
#include <iostream>
struct HelpBase {
int a = 0;
virtual void output() {}
};
struct HelpDerived : HelpBase {
int b = 0;
void output() override {}
};
class Base {
public:
virtual HelpBase create() = 0;
};
class Derived : public Base {
public:
HelpBase create() override;
};
HelpBase Derived::create() {
HelpDerived d;
d.a = 1;
d.b = 2;
return d;
}
int main() {
Derived d;
auto based = d.create();
HelpDerived derived = dynamic_cast<HelpDerived &>(based);
std::cout << derived.a << std::endl;
}
When I run the code abve, I get the error
terminate called after throwing an instance of 'std::bad_cast'
what(): std::bad_cast
Abort trap: 6
What have I misunderstood about objects and casting in C++? Why does this method not work?
What can I do to fix the problem?
I think you'd better return a pointer to avoid object slicing in your create function.
#include <iostream>
struct HelpBase {
int a = 0;
virtual void output() {}
};
struct HelpDerived : HelpBase {
int b = 0;
void output() override {}
};
class Base {
public:
virtual HelpBase* create() = 0;
};
class Derived : public Base {
public:
HelpBase* create() override;
};
HelpBase* Derived::create() {
HelpDerived* d = new HelpDerived;
d->a = 1;
d->b = 2;
return d;
}
int main() {
Derived d;
auto based = d.create();
HelpDerived* derived = dynamic_cast<HelpDerived *>(based);
std::cout << derived->a << " " << derived->b << std::endl;
delete derived;
}
I've replaced dynamic cast by static cast and it worked for me almost fine.
#include <iostream>
struct HelpBase {
int a = 0;
virtual void output() {}
};
struct HelpDerived : HelpBase {
int b = 0;
void output() override {}
};
class Base {
public:
virtual HelpBase create() = 0;
};
class Derived : public Base {
public:
HelpBase create() override;
};
HelpBase Derived::create() {
HelpDerived d;
d.a = 3;
d.b = 2;
return d;
}
int main() {
Derived d;
auto based = d.create();
HelpDerived derived = static_cast<HelpDerived &>(based);
std::cout << derived.a << std::endl;
std::cout << derived.b << std::endl;
}
Output:
3
32726
Note that a value is correct, while b is junk. This is because for derived constructor has not been called.
In general, casting from base class to derived is not recommended, as derived may have more data members, than base class.
Recommended reading: https://www.bogotobogo.com/cplusplus/upcasting_downcasting.php
i need to call the overidden function inside B class through C class but it gives "Base" as a output rather than "Derived". when I call this code part classC.getTargetB().example(); i need to get "Derived" as a output. how can i reach my goal in the code.
class A {
public:
A() {};
virtual void example() { std::cout << "Base" << std::endl; }
};
class B :public A {
protected:
std::string name;
public:
B() {};
B(std::string n) { name = n; }
void example() override { std::cout << "Derived" << std::endl; }
};
class C {
protected:
std::vector<std::shared_ptr<A>> ptr;
std::shared_ptr<A> targetBobject;
public:
void setB(std::shared_ptr<A> target) {
targetBobject = target;
}
A getTargetB() {
return *targetBobject;
}
};
int main()
{
A example;
std::vector<std::shared_ptr<A>> parent;
C classC;
std::shared_ptr<B> ptr1 = std::make_shared<B>("B1");
std::shared_ptr<B> ptr2 = std::make_shared<B>("B2");
parent.push_back(std::move(ptr1));
parent.push_back(std::move(ptr2));
//parent.at(0)->example(); this gives 'Derived' as a output
classC.setB(parent.at(0));
classC.getTargetB().example();// gives 'Base' as a output
}
I have a class derived from an interface and a friend class of the derived class. I want to access the members of derived class which is instantiated as interface. It looks like this:
Interface:
class AInterface
{
public:
virtual ~AInterface() = default;
virtual void set(int a) = 0;
};
Derived class A with friend class B:
class B;
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
private:
friend class B;
int mem = 0;
};
class B:
class B
{
public:
B()
{
a = new A();
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->mem;
}
private:
AInterface *a;
}
main:
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
The program does not compile saying AInterface has no member named 'mem'.
Do I need getter functions in the interface and implement it in A to achieve this or is there any other way to do it?
Now work
#include <iostream>
using namespace std;
class AInterface
{
public:
virtual ~AInterface() = default;
int getMem() { return mem; }
virtual void set(int a) = 0;
protected:
int mem = 0;
};
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
};
class B
{
public:
B()
{
a = new A{};
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->getMem();
}
private:
AInterface *a;
};
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
Method which is override by child and is pure, should be virtual.
If each class (child) Interface, variable int mem should be protected in interface.
Now works fine, like you want.
Add getter getMem()
Version with friend
#include <iostream>
using namespace std;
class AInterface
{
public:
virtual ~AInterface() = default;
virtual void set(int a) = 0;
protected:
friend class B;
int mem = 0;
};
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
};
class B
{
public:
B()
{
a = new A{};
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->mem;
}
private:
AInterface *a;
};
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
In your class B.
class B
{
//...
int get_a()
{
return a->mem; // but a is a AInterface* !!!
}
private:
AInterface *a; // That's not an A*, but an AInterface*
};
You have 2 options.
use dynamic_cast<>
int B::get_a()
{
A* p = dynamic_cast<A*>(a);
if (p)
return p->mem;
// a is not an A*, it's another AInterface*-type object !!!
// What should you do?
throw something_or_other(); // throw?
return -1; // return an error code?
}
// or maybe add.. so you can check for errors before calling get_a()
A* B::get_A_ptr() const
{
return dynamic_cast<A*>(a);
}
dynamic_cast works fine, but can slow down your app if you need to make frequent reads of a->mem.
Store a in an A*, which is probably what you meant to do from the start...
class B
{
// ...
private:
A* a; // now a->A::mem is visible.
};
Since you explicitly call new A in B's constructor, I think option 2 is better for your case.
I have some code like:
class Base {
virtual bool acceptsData(char*) = 0;
};
class Derived1 : public Base {
virtual bool acceptsData(char*) { /* do something */ }
};
class Derived2 : public Base {
virtual bool acceptsData(char*) { /* do something else */}
}
Base* createStuff(char* data)
{
Base* d1 = new Derived1();
if(d1->acceptsData(data))
{
return d1;
}
delete d1;
Base* d2 = new Derived2();
if(d2->acceptsData(data))
{
return d2;
}
delete d2;
// and more ...
}
// .... somewhere later
int main()
{
Base* Aclass = createStuff("abc");
}
I'd like to get rid of this long if() ... construct, and use some more generalized patterns, but I still did not manager to come up with something useful. Is there a better way of doing this?
If you want to factorize code as you have several Derived classes, you may use something like the following:
namespace detail
{
template <typename T> std::unique_ptr<Base> make_base(const char* data)
{
std::unique_ptr<Base> base = std::make_unique<T>();
if (base->acceptsData(data)) {
return base;
}
return nullptr;
}
template <typename... Ts> std::unique_ptr<Base> createStuff(const char* data)
{
std::function<std::unique_ptr<Base>(const char*)> fs[] = { make_base<Ts>... };
for(auto& f : fs) {
auto base = f(data);
if(base) {
return base;
}
}
return nullptr;
}
}
Base* createStuff(const char* data) {
return detail::createStuff<Derived1, Derived2/* and other Derived classes*/>(data).release();
}
Live example.
You are creating your objects. Factory or Builder are suitable patterns for you.
What might meet your requirements is something the virtual constructors design pattern. This is what it looks like...
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Base {
Base* b;
// suppress the usual constructors
Base(Base&);
Base operator=(Base&);
protected:
Base() { b = 0; };
public:
virtual void Print() { b->Print(); }
virtual ~Base() {
if (b) {
delete b;
}
}
Base(string type);
};
class Derived1 : public Base {
Derived1(Derived1&);
Derived1 operator=(Derived1&);
Derived1() {}
friend class Base;
public:
void Print() { cout << "Derived1::Print()" << endl; }
~Derived1() { }
};
class Derived2 : public Base {
Derived2(Derived2&);
Derived2 operator=(Derived2&);
Derived2() {}
friend class Base;
public:
void Print() { cout << "Derived2::Print()" << endl; }
~Derived2() { }
};
Base::Base(string type) {
if (type == "Derived1")
b = new Derived1;
else if (type == "Derived2")
b = new Derived2;
}
int main() {
vector<Base*> bases;
cout << "virtual constructor calls:" << endl;
bases.push_back(new Base("Derived2"));
bases.push_back(new Base("Derived1"));
bases.push_back(new Base("Derived1"));
bases.push_back(new Base("Derived2"));
for (int i = 0; i < bases.size(); i++) {
bases[i]->Print();
}
cout << "destructor calls:" << endl;
for (int j = 0; j < bases.size(); j++) {
delete bases[j];
}
// system("pause");
return 0;
}
I need a base class that gives me primitive type of data's pointer. I add a function in it. I derived types of class. I used void * to support all primitive types as a return type but it is like old C days. It is not good for OOP. Does one have an suggestion to do in a proper way in OOP?
#include <iostream>
class base {
public:
virtual void *getPtr() = 0;
virtual ~base() {};
};
class derivedAType : public base {
protected:
int _i;
public:
derivedAType(int i): _i(0) { _i = i; };
virtual ~derivedAType() {}
virtual void *getPtr() {
return static_cast<void *>(&_i);
}
};
class derivedBType : public base {
protected:
short _s;
public:
derivedBType(short s): _s(0) { _s = s; };
virtual ~derivedBType() {}
virtual void *getPtr() {
return static_cast<void *>(&_s);
}
};
int main()
{
base *b1 = new derivedAType(1203912);
base *b2 = new derivedBType(25273);
std::cout << "b1 : " << *(static_cast<int *>(b1->getPtr()))
<< "\nb2 : " << *(static_cast<short *>(b2->getPtr()))
<< std::endl;
delete b2;
delete b1;
return 0;
}
Make the base class a template class with the data type as the template variable
template<typename DataType>
class base {
virtual DataType* getPtr() = 0;
//...
};
and
class derivedAType : public base<int>
But this changes base class to a template class which means you cant store them together, base<int> is different from base<short>
If this isnt acceptable, the other options is just a tad bit cleaner than your code but abt the same, refer to this question. Basically derived class return types can reflect their true type and i think it should get automatically converted to void*, so you dont have to manually cast the pointer.
Not sure about your problem. But maybe a double callback can help:
class Callback {
public:
virtual void do_int( int i ) const = 0;
virtual void do_short( short s ) const = 0;
/* ... */
}
class base {
public:
virtual void do_stuff(const Callback & c); /* will need a more telling name */
virtual ~base() {};
};
class derivedAType : public base {
protected:
int _i;
public:
derivedAType(int i): _i(0) { _i = i; };
virtual ~derivedAType() {}
virtual void do_stuff(const Callback & c) {
c.do_int( _i );
}
};
class derivedBType : public base {
protected:
short _s;
public:
derivedBType(short s): _s(0) { _s = s; };
virtual ~derivedBType() {}
virtual void do_stuff( const Callback & c) {
c.do_short( _s );
}
};
class print_callback : public Callback {
public:
virtual void do_int( int i ) const { std::cout << i; }
virtual void do_short( short s ) const { std::cout << s; }
}
int main() {
base *b1 = new derivedAType(1203912);
base *b2 = new derivedBType(25273);
std::cout << "b1 : ";
b1->do_stuff(print_callback());
std::cout << "\nb2 : ";
b2->do_stuff(print_callback());
std::cout << std::endl;
delete b2;
delete b1;
return 0;
}
Of course you can simplify this by just storing the created print callback, and using it twice.