Base class pointer: where to use new and delete - c++

I wonder where I should use the new and delete in the following class structure:
#include <iostream>
class StateBase {
public:
StateBase( int val ) : m_stateInfo(val) {}
virtual ~StateBase() {}
virtual int getState() = 0;
protected:
int m_stateInfo;
};
class StateImpl1 : public StateBase {
public:
StateImpl1() : StateBase( 1 ) {}
~StateImpl1() {}
int getState() {
//std::cout << "stateimpl:" << m_stateInfo << std::endl;
return m_stateInfo;
}
};
class DeviceBase {
public:
DeviceBase( StateBase* pState ) : mp_state( pState ) {}
~DeviceBase() {} // TODO or delete here? but then it's a bit asymmetric...
virtual void work() = 0;
protected:
StateBase* mp_state;
};
class DeviceImpl1 : public DeviceBase {
public:
DeviceImpl1() : DeviceBase( new StateImpl1() ) {}
// TODO d'tor here? but then base is left without valid ptr to "mp_state"
~DeviceImpl1() { delete mp_state; }
void work() {
std::cout << "DeviceImpl1 work: state = " << mp_state->getState() << std::endl;
}
};
int main() {
DeviceImpl1 impl1;
impl1.work();
return 0;
}
Having the delete in the base class is asymmetric and less readable, I guess.
Using delete in the derived class (where the new is invoked) leaves the base class with a invalid pointer (if only shortly, but it's not clean).
using it in derived class, setting ptr to NULL and and checking pointer for NULL in the base class could be an option
maybe the whole design is flawed? if so: what's an alternative?
Update:
I can not use modern C++ because it will have to be compiled with a cross compiler < C++11.

Use unique_ptr to manage ownership/lifetime/memory:
#include <iostream>
#include <memory>
#include <utility>
class StateBase {
public:
StateBase( int val ) : m_stateInfo(val) {}
virtual ~StateBase() {}
virtual int getState() = 0;
protected:
int m_stateInfo;
};
class StateImpl1 : public StateBase {
public:
StateImpl1() : StateBase( 1 ) {}
~StateImpl1() {}
int getState() {
return m_stateInfo;
}
};
class DeviceBase {
public:
DeviceBase( std::unique_ptr<StateBase> ) : mp_state( std::move(pState) ) {}
virtual ~DeviceBase() {}
virtual void work() = 0;
protected:
std::unique_ptr<StateBase> mp_state;
};
class DeviceImpl1 : DeviceBase {
public:
DeviceImpl1() : DeviceBase( std::make_unique<StateImpl1>() ) {}
~DeviceImpl1() = default;
void work() {
std::cout << "DeviceImpl1 work: state = " << mp_state->getState() << std::endl;
}
};
int main() {
DeviceImpl1 impl1;
impl1.work();
return 0;
}

In modern C++, you would 1. figure out the desired ownership semantics and then 2. express them using appropriate memory management tools, such as smart pointers. Notably, you never manually do memory management. That's effort that should be encapsulated in a class whose sole responsibility is memory management (see single responsibility principle).
#include <iostream>
#include <memory>
class StateBase {
public:
StateBase( int val ) : m_stateInfo(val) {}
virtual ~StateBase() {}
virtual int getState() = 0;
protected:
int m_stateInfo;
};
class StateImpl1 : public StateBase {
public:
StateImpl1() : StateBase( 1 ) {}
~StateImpl1() {}
int getState() {
//std::cout << "stateimpl:" << m_stateInfo << std::endl;
return m_stateInfo;
}
};
class DeviceBase {
public:
// Constructor says: Give me exclusive ownership of a StateBase.
DeviceBase(std::unique_ptr<StateBase> pState) : mp_state(std::move(pState)) {}
// Destructor (implicitly generated) takes care of cleanup.
virtual void work() = 0;
protected:
std::unique_ptr<StateBase> mp_state;
};
class DeviceImpl1 : DeviceBase {
public:
DeviceImpl1() : DeviceBase(std::make_unique<StateImpl1>()) {}
// Base class constructor handles cleanup.
void work() {
std::cout << "DeviceImpl1 work: state = " << mp_state->getState() << std::endl;
}
};
int main() {
DeviceImpl1 impl1;
impl1.work();
return 0;
}
All we did here was to clarify that DeviceBase holds unique ownership of a StateBase. By doing that, we can eliminate all the destructors (std::unique_ptr handles the memory management for us, see also RAII). I would prefer = default; over an empty destructor implementation but that's largely immaterial. The automatically generated destructor of DeviceBase will call the unique_ptr destructor which will delete the stored StateBase instance.
Note that your original code does not follow the rule of three/five/zero, therefore you would run into problems (read: double free etc.) when attempting to copy instances of your class. In the above code using std::unique_ptr, the DeviceBase and DeviceImpl1 classes cannot be copied (because the std::unique_ptr member cannot be copied).

Inherit public base class :
#include <iostream>
class StateBase {
public:
StateBase(int val) : m_stateInfo(val) {}
virtual ~StateBase() {}
virtual int getState() = 0;
protected:
int m_stateInfo;
};
class StateImpl1 : public StateBase {
public:
StateImpl1() : StateBase(1) {}
~StateImpl1() {}
int getState() {
//std::cout << "stateimpl:" << m_stateInfo << std::endl;
return m_stateInfo;
}
};
class DeviceBase {
public:
DeviceBase(StateBase* pState) : mp_state(pState) {}
~DeviceBase() {} // TODO or delete here? but then it's a bit asymmetric...
virtual void work() = 0;
protected:
StateBase* mp_state;
};
class DeviceImpl1 : **public DeviceBase** { // Change is here
public:
DeviceImpl1() : DeviceBase(new StateImpl1()) {}
// TODO d'tor here? but then base is left without valid ptr to "mp_state"
~DeviceImpl1() { delete mp_state; }
void work() {
std::cout << "DeviceImpl1 work: state = " << mp_state->getState() << std::endl;
}
};
How you can initialize the DeviceImpl1 instance impl1 & call delete to execute both of the destructors :
int main() {
DeviceImpl1* impl1 = new DeviceImpl1();
DeviceBase* base = impl1;
impl1->work();
delete base; // This will execute both of the destructor.
return 0;
}

Related

Compile error associated with std::unique_ptr and abstract classes

I have class that inherits from a base class. The base class contains pure virtual functions that are overridden in the derived class. I instantiate the base class object with std::unique_ptr of the derived class but get a compile time error
class Base {
public:
~Base () = default;
initBase () { count = 0; }
virtual void method1() = 0;
virtual void method2() = 0;
private:
int count;
};
class Child final : public Base {
public:
Child() = default;
~Child() = default;
void method1() override { std::cout << "B Running method 1\n"; }
void method2() override { std::cout << "B Running method 2\n"; }
};
class myClass {
public:
myClass(std::unique_ptr<Base> base) { _base(std::move(base)) };
~myClass() = default();
private:
std::unique_ptr<Base> _base;
};
int main() {
myClass obj = myClass(std::make_unique<Child>());
}
Compiler gives the following error:
error: invalid new-expression of abstract class type 'Base'
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
because the following virtual functions are pure within 'Base':
class A {
'virtual void Base::method1()'
virtual void method1() = 0;
'virtual void Base::method2()'
virtual void method2() = 0;
There are several typos in your code:
In Base:
Change
initBase () { count = 0; }
to
Base () { count = 0; }
In Child:
change
myClass(std::unique_ptr<Base> base) { _base(std::move(base)) };
to
myClass(std::unique_ptr<Base> base) : _base(std::move(base)) { }
change
~myClass() = default();
to
~myClass() = default;
In main():
change
myClass obj = myClass(std::make_unique<Child>());
to
myClass obj(std::make_unique<Child>());
#include <iostream>
#include <memory>
class Base {
public:
~Base () = default;
Base () { count = 0; }
virtual void method1() = 0;
virtual void method2() = 0;
private:
int count;
};
class Child final : public Base {
public:
Child() = default;
~Child() = default;
void method1() override { std::cout << "B Running method 1\n"; }
void method2() override { std::cout << "B Running method 2\n"; }
};
class myClass {
public:
myClass(std::unique_ptr<Base> base) : _base(std::move(base)) { }
~myClass() = default;
private:
std::unique_ptr<Base> _base;
};
int main() {
myClass obj(std::make_unique<Child>());
std::cout << "OK";
}
With those fixes in place, the code compiles fine.
Live Demo

Why does 'visitor pattern' asks each class to inherit VisitorHost interface class which has accept() function?

I am learning a design pattern, vistor pattern, in c++.
At first, I copy my two practice codes below. First one is "my test code", and the second one is a simplified code of "normal visitor pattern" in my text book. I would like you to read the first code but the second one is just a reference code of normal visitor pattern.
My question is why visitor pattern asks each class to inherit VisitorsHostInterface class which has virtual function, accept(); please refer to the second code, "normal visitor pattern", below if necessary. In my understanding, it is not necessary to use accept() function to scan all instances, like the first code, "my test code".
I suppose "my test code" is simpler than "normal visitor pattern".
Please tell me the reason why visitor pattern asks accept() function to each class? Thank you very much.
(1) my test code
class ClassD;
class ClassC {
public:
ClassC(int new_value, ClassD* new_next_object) : value_(new_value), next_object_(new_next_object) {};
void print() { std::cout << "ClassC value_ = " << value_ << std::endl; }
int value() { return value_; }
std::shared_ptr<ClassD> next_object(void) { return next_object_; }
private:
int value_=0;
std::shared_ptr<ClassD> next_object_;
};
class ClassD {
public:
ClassD(int new_value, ClassC* new_next_object) : value_(new_value), next_object_(new_next_object) {};
void print() { std::cout << "ClassD value_ = " << value_ << std::endl; }
int value() { return value_; }
std::shared_ptr<ClassC> next_object(void) { return next_object_; }
private:
int value_=0;
std::shared_ptr<ClassC> next_object_;
};
class VisitorFuncInterface {
public:
virtual ~VisitorFuncInterface() = default;
virtual void visit(ClassC* obj) = 0;
virtual void visit(ClassD* obj) = 0;
};
class VisitorFunc : public VisitorFuncInterface {
public:
virtual ~VisitorFunc() = default;
void visit(ClassC* obj) {
if (obj) {
obj->print();
this->visit(obj->next_object().get());
}
}
void visit(ClassD* obj) {
if (obj) {
obj->print();
this->visit(obj->next_object().get());
}
}
};
void test_visitor_without_host(void) {
ClassD* d0 = new ClassD(0, nullptr);
ClassC* c0 = new ClassC(1, d0);
ClassD* d1 = new ClassD(2, c0);
VisitorFunc v;
v.visit(d1);
delete d1;
}
The result of test_visitor_without_host() is following,
ClassD value_ = 2
ClassC value_ = 1
ClassD value_ = 0
(2) normal visitor pattern code
class ClassA;
class ClassB;
class VisitorInterface {
public:
virtual ~VisitorInterface() = default;
virtual void visit(ClassA* obj) = 0;
virtual void visit(ClassB* obj) = 0;
};
class VisitorsHostInterface { // = visitor's host
public:
virtual ~VisitorsHostInterface() = default;
virtual void accept(VisitorInterface& v) = 0;
};
class VisitorsHost : public VisitorsHostInterface {
public:
virtual ~VisitorsHost();
void accept(VisitorInterface& v) {};
};
class ClassA : public VisitorsHostInterface {
public:
ClassA(int new_value, ClassB* new_next_object) : value_(new_value), next_object_(new_next_object) {};
void print() { std::cout << "ClassA value_ = " << value_ << std::endl; }
int value() { return value_; }
std::shared_ptr<ClassB> next_object(void) { return next_object_; }
void accept(VisitorInterface& v) { v.visit(this); };
private:
int value_=0;
std::shared_ptr<ClassB> next_object_;
};
class ClassB : public VisitorsHostInterface {
public:
ClassB(int new_value, ClassA* new_next_object) : value_(new_value), next_object_(new_next_object) {};
void print() { std::cout << "ClassB value_ = " << value_ << std::endl; }
int value() { return value_; }
std::shared_ptr<ClassA> next_object(void) { return next_object_; }
void accept(VisitorInterface& v) { v.visit(this); };
private:
int value_=0;
std::shared_ptr<ClassA> next_object_;
};
class Visitor : public VisitorInterface {
public:
virtual ~Visitor() = default;
void visit(ClassA* obj) {
if (obj) {
obj->print();
this->visit(obj->next_object().get());
}
}
void visit(ClassB* obj) {
if (obj) {
obj->print();
this->visit(obj->next_object().get());
}
}
};
void test_visitor(void) {
ClassB* b0 = new ClassB(0, nullptr);
ClassA* a0 = new ClassA(1, b0);
ClassB* b1 = new ClassB(2, a0);
Visitor v;
b1->accept(v);
delete b1;
}
The result of test_visitor() is following,
ClassB value_ = 2
ClassA value_ = 1
ClassB value_ = 0
In your example, you hold all the objects by value and know their static & dynamic type. You don't need dynamic dispatch, so you don't need to have a common VisitorsHostInterface base class. All that's required is for your classes to implement an accept function.
However, the visitor pattern is most commonly used when you don't have access to the dynamic type of the visited objects. Say you have a vecotr<unique_ptr<Widget>>. Where many different Widget sub-types are stored by pointer. Than Widget and every one of its sub classes must implement a virtual accept function. To get to the objects dynamic type, you need to do dynamic dispatch.

C++ Using the function of the class two class above

I have the current setup:
class Interface1
{
public:
virtual ~Interface1() {}
virtual void DoSomething() = 0;
};
class Interface2 : public virtual Interface1
{
public:
virtual ~Interface2() {}
virtual void DoSomething() override = 0;
virtual void DoSomethingElse() = 0;
};
class MyClass1 : public Interface1
{
public:
MyClass1();
void DoSomething() override;
};
class MyClass2 : public Interface2
{
public:
MyClass2();
void DoSomething() override;
void DoSomethingElse() override;
};
int main()
{
std::map<std::string, boost::any> items;
items.insert(make_pair("item1", shared_ptr<Interface1>(new MyClass1())));
items.insert(make_pair("item2", shared_ptr<Interface2>(new MyClass2())));
auto object = items.at("item2");
auto item = boost::any_cast<shared_ptr<Interface1>>(object);
item->DoSomething();
return 0;
}
When I run this code, nothing happens. MyClass2 doesn't appear to be calling DoSomething(), which is what I would like. How can I make the call to Interface1::DoSomething() actually call Interface2::DoSomething()? I would think it would be possible because they all inherit from each other, but I can't seem to make it work.
The reason I want this is because I have some functions which will only work with classes inherited from Interface2, but some functions need to support classes derived from either Interface1 and Interface2. Once boost::any takes over I loose which type it originally was, but it shouldn't be a problem if I could use the setup described above, so even if my original class was derived from Interface2, it could call the same function in Interface1 and get the same result.
Is there a way of doing what I want with the current setup?
EDIT:
Sorry, the void in front of the constructors where my bad, but that is not the issue.
Why do you need the boost::any?
If you need to determine the difference between Interface1 and Interface2, and you have a std::shared_pointer stored in your map, then just store a std::shared_pointer<Interface1> and use std::dynamic_pointer_cast<Interface2> to determine whether you have an Interface1 or an Interface2
Example:
#include <map>
#include <memory>
#include <iostream>
class Interface1
{
public:
virtual ~Interface1() = default;
virtual void DoSomething() = 0;
};
class Interface2 : public Interface1
{
public:
virtual ~Interface2() = default;
virtual void DoSomethingElse() = 0;
};
class MyClass1 : public Interface1
{
public:
MyClass1() {}
void DoSomething() override { std::cout << "\t\t" << __PRETTY_FUNCTION__ << '\n'; }
};
class MyClass2 : public Interface2
{
public:
MyClass2() {}
void DoSomething() override { std::cout << "\t\t" << __PRETTY_FUNCTION__ << '\n'; }
void DoSomethingElse() override { std::cout << "\t\t" << __PRETTY_FUNCTION__ << '\n'; }
};
int main()
{
std::map<std::string, std::shared_ptr<Interface1>> items;
items.emplace("item1", std::make_shared<MyClass1>());
items.emplace("item2", std::make_shared<MyClass2>());
auto check = [&items](const std::string& name)
{
auto object = items.at(name);
auto item = std::dynamic_pointer_cast<Interface2>(object);
if (item)
{
std::cout << name << " is an Interface2\n";
item->DoSomething();
item->DoSomethingElse();
}
else
{
std::cout << name << " is an Interface1\n";
object->DoSomething();
}
};
check("item1");
check("item2");
return 0;
}
Output:
item1 is an Interface1
virtual void MyClass1::DoSomething()
item2 is an Interface2
virtual void MyClass2::DoSomething()
virtual void MyClass2::DoSomethingElse()
Some final notes:
I also question the need for virtual inheritance between Interface2 and Interface1
I don't believe you need to override DoSomething in Interface2 - it's already there by publically inheriting from Interface1
virtual void DoSomething() override = 0; is unnecessary
It's not useful, but it works:
Live On Coliru
#include <map>
#include <iostream>
class Interface1
{
public:
virtual ~Interface1() {}
virtual void DoSomething() = 0;
};
class Interface2 : public virtual Interface1
{
public:
virtual ~Interface2() {}
virtual void DoSomething() override = 0;
virtual void DoSomethingElse() = 0;
};
class MyClass1 : public Interface1
{
public:
MyClass1() {}
void DoSomething() override { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
class MyClass2 : public Interface2
{
public:
MyClass2(){}
void DoSomething() override { std::cout << __PRETTY_FUNCTION__ << "\n"; }
void DoSomethingElse() override { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
#include <memory>
#include <boost/any.hpp>
int main()
{
using std::shared_ptr;
std::map<std::string, boost::any> items;
items.insert(make_pair("item1", shared_ptr<Interface1>(new MyClass1())));
items.insert(make_pair("item2", shared_ptr<Interface2>(new MyClass2())));
{
auto object = items.at("item1");
auto item = boost::any_cast<shared_ptr<Interface1>>(object);
item->DoSomething();
}
{
auto object = items.at("item2");
auto item = boost::any_cast<shared_ptr<Interface2>>(object);
item->DoSomething();
}
return 0;
}
Prints
virtual void MyClass1::DoSomething()
virtual void MyClass2::DoSomething()
Of course you need to cast to the correct interface
Found the problem. Here are the correct definitions for MyClass1 and MyClass2 :
class MyClass1 : public Interface1
{
public:
MyClass1();
void DoSomething() override;
};
class MyClass2 : public Interface2
{
public:
MyClass2();
void DoSomething() override;
void DoSomethingElse() override;
};
You have declared your constructors as void MyClass1(), which is illegal. The correct constructor syntax is MyClass1().
I don't know which compiler you're using, but I'd throw it out for not raising a syntax error.

C++ virtual functions base return type suggestions

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.

Is it possible to adapt the "Prototype pattern" to rvalue references?

I have a hierarchie of classes that implement the Prototype pattern and I would like to use move semantics to limit objects deep copy. I tried to adapted the pattern with a move() member function which meaning is that I do not need the original object anymore. Here is what I have so far:
#include <iostream>
#include <utility>
#include <vector>
struct base
{
virtual ~base() { }
virtual base* clone() const = 0;
virtual base* move() = 0;
};
struct derived1 : public base
{
derived1() { std::cout << "derived1::derived1()\n"; }
derived1(const derived1&) { std::cout << "derived1::derived1(const derived1&)\n"; }
derived1(derived1&&) { std::cout << "derived1::derived1(derived1&&)\n"; }
virtual ~derived1() { }
virtual base* clone() const { return new derived1(*this); }
virtual base* move() { return new derived1(std::move(*this)); }
};
struct derived2 : public base
{
derived2() { std::cout << "derived2::derived2()\n"; }
derived2(const derived2&) { std::cout << "derived2::derived2(const derived2&)\n"; }
derived2(derived2&&) { std::cout << "derived2::derived2(derived2&&)\n"; }
virtual ~derived2() { }
virtual base* clone() const { return new derived2(*this); }
virtual base* move() { return new derived2(std::move(*this)); }
};
std::vector<base*> vec;
void foo(const base& obj)
{
vec.push_back(obj.clone());
}
void foo(base&& obj)
{
vec.push_back(obj.move());
}
int main()
{
derived1 d1;
derived2 d2;
foo(d1);
foo(d2);
foo(derived1());
foo(derived2());
}
When I run it, it show that the good constructors are used:
derived1::derived1()
derived2::derived2()
derived1::derived1(const derived1&)
derived2::derived2(const derived2&)
derived1::derived1()
derived1::derived1(derived1&&)
derived2::derived2()
derived2::derived2(derived2&&)
So far, it seems good. I am just not sure if this is a standard compliant usage of the rvalue references. Is there a point I did not think of that would produce undesirable results?
For recurring method definition I prefer CRTP. For your case I'd declare something like:
template<typename TDerived>
class virtually_clonable : public base
{
public:
virtual base* clone() override
{
return new TDerived(*AsDerived());
}
virtual base* move() override
{
return new TDerived(std::move(*AsDerived()));
}
private:
TDerived* AsDerived()
{
return static_cast<TDerived*>(this);
}
};
And while implementing the classes:
class derived1 : public virtually_clonable<derived1>
{
public:
/* your ctors goes here*/
/* no need to implement clone/move again */
};
class derived2 : public virtually_clonable<derived2>
{
public:
/* your ctors goes here*/
/* no need to implement clone/move again */
};
By the way you may want to return shared_ptr objects instead of raw pointers. That is usually the case for clonable types instead of unique_ptr.