shared_ptr and private inheritance - c++

Here's a toy example illustrating a problem I encounter. The application is fairly irrelevant (it's essentially a linked list of elements with a special behavior at the end). I'm unable to construct a base class shared_ptr with a derived pointer and it's for some reason linked to the fact that I'm using private inheritance.
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
using namespace std;
// An Item in a linked list
class A
{
public:
//friend class B;
typedef boost::shared_ptr<A> APtr;
A() : next_() {}
A(APtr n) : next_(n) {}
APtr next() { return next_; }
void setNext(APtr n) { next_ = n; }
virtual void doIt() { /* standard behavior */ }
private:
APtr next_;
};
class B : private A // B really is a special A
// that should have different behavior
// at the tail of the chain
// but I want to hide A's interface
// to external clients
{
public:
typedef boost::shared_ptr<B> BPtr;
B(A::APtr prev)
{ // Set this object as the tail
prev->setNext(APtr(this)); /* WHY CAN'T I CONSTRUCT APtr(this)
WITH PRIVATE INH. */
}
void doIt() {/*special behavior at end */}
};
int main()
{
A::APtr dummyPtr;
A::APtr head = boost::make_shared<A>(dummyPtr);
B::BPtr tail = boost::make_shared<B>(head);
for(A::APtr curr = head; curr; curr=curr->next()){
curr->doIt();
}
return 0;
}
and I get this
/usr/include/boost/smart_ptr/shared_ptr.hpp: In constructor ‘boost::shared_ptr<T>::shared_ptr(Y*) [with Y = B, T = A]’:
derived_shared.cpp:31: instantiated from here
/usr/include/boost/smart_ptr/shared_ptr.hpp:352: error: ‘A’ is an inaccessible base of ‘B’
I was under the impression that private inheritance allows the Derived class to still access the public interface of the base class but hides that interface to external clients. Why does private inheritance cause this error (it works if I inherit publicly)?

Change this single line:
prev->setNext(APtr(this));
to
prev->setNext(APtr(static_cast<A*>(this)));
And it compiles.
Or at least it does when using the std library. It is usually similar for boost.
There are other errors but that gets round casting B* to A*.
Why does that work? Because the template for the constructor std::shared_ptr<A> isn't what you think it is! It is more like template <class X> std::shared_ptr(X* v). So the actual B* to A* cast is postponed and failing in a non-friend member.
But if you cast the B* pointer (i.e. this) to A* inside a method of class B (the only place that is legal without a friend declaration) you're in.
NB: There is nothing in principle wrong with private inheritance. It isn't an anti-pattern and is provided for good reason. Do think about composition but objects that forbid some parts of the application from 'accessing' their 'real' type have lots of uses. For example pass out an object A that has some B bolt ons that only the object factory can access.
PS: The reason why the constructor is template<class T> shared_ptr<T* v> is so that shared_ptr uses the deleter of the type passed into it.
As you're not doubt aware share_ptr cleverly calls the 'right' destructor even if it isn't virtual.
My 'fix' actually subverts that cleverness so beware to pass in the right deleter or (recommended) make the destructor of A virtual.
PPS:
And finally a fully working program (using STL. Sorry I don't have Boost):
#include <iostream>
#include <memory>
// An Item in a linked list
class A
{
public:
//friend class B;
typedef std::shared_ptr<A> APtr;
A() : next_() {}
A(APtr n) : next_(n) {}
APtr next() { return next_; }
void setNext(APtr n) { next_ = n;}
virtual void doIt() { std::cout<<"normal thing"<<std::endl; }
virtual ~A(){}
private:
APtr next_;
};
class B : public std::enable_shared_from_this<A>, private A // B really is a special A
// that should have different behavior
// at the tail of the chain
// but I want to hide A's interface
// to external clients
{
public:
template<class X> friend class std::enable_shared_from_this;
typedef std::shared_ptr<B> BPtr;
static BPtr makeit(A::APtr prev){
BPtr B(std::make_shared<B>());
prev->setNext(B->shared_from_this());
return B;
}
void doIt() {std::cout<<"end thing"<<std::endl;}
private:
B(){}
};
int main()
{
A::APtr dummyPtr;
A::APtr head = std::make_shared<A>(dummyPtr);
B::BPtr tail = B::makeit(head);
for(A::APtr curr = head; curr; curr=curr->next()){
curr->doIt();
}
return 0;
}
You need to use enable_shared_from_this because otherwise you're trying to create two 'families' of shared_ptr and that won't work.
I've made a factory method because fixing the constructor just wouldn't work!
There is a precondition of enable_shared_from_this that there has to be a std::shared_ptr in existence and I suppose that means 'fully constructed'.
The following constructor will not work for me:
B(A::APtr prev){
prev->setNext(shared_from_this());
}
That said, if you do inherit from enable_shared_from_this it's a good idea to make all the constructors private and provide factories that return shared_ptr. Otherwise you can get in a right mess if calling code doesn't itself ensure that 'pre-existing shared_ptr' condition. A nasty piece of coupling if ever there was one.

When you use private inheritance, you're basically saying "I want B to be implemented in terms of A, but I don't want it to be used like a A (is-a A)"
Here, you're giving boost::shared_ptr a pointer to B as if it was an A.
That's a contradiction in your design. Maybe declaring boost::shared_ptr<A> a friend of B would help, but it's still a weird design.
Additional note: If you want B to be a special A that doesn't expose A's interface, consider composition instead of private inheritance

Related

Virtual Function During Construction Workaround

I've got a base class that has a virtual function. I want to call that class during the construction because I want the function called for each of the derived classes. I know I can't call a virtual function during construction, but I can't think of an elegant (i.e., avoid repeating code) solution.
What are some work arounds to calling a virtual function during construction?
The reason I want to avoid this is because I don't want to have to create constructors that just call the base class.
class A {
public:
A() {
read();
}
// This never needs to be called
virtual void read() = 0;
}
class B:A {
public:
B():A() { };
read() { /*Do something special for B here.*/ }
}
class C:A {
public:
C():A() { };
read() { /*Do something special for C here.*/ }
}
PS: The Python way of doing this is simply to raise NotImplementedError in A::read(). I'm returning to C++ and I'm more rusty than I thought.
The FAQ perspective.
This is a Frequently Asked Question.
See the C++ FAQ item titled “Okay, but is there a way to simulate that behavior as if dynamic binding worked on the this object within my base class's constructor?”.
It’s very often a good idea to check the FAQ (and generally, googling or altavista’ing) before asking.
The question as “Derived class specific base initialization”.
To be clear, while the literal question above is
“What are some work arounds to calling a virtual function during construction?”
it is evident that what’s meant is
“How can a base class B be designed so that each derived class can specify part of what goes on during B construction?”
A major example is where C style GUI functionality is wrapped by C++ classes. Then a general Widget constructor might need to instantiate an API-level widget which, depending on the most derived class, should be a button widget or a listbox widget or whatever. So the most derived class must somehow influence what goes on up in Widget’s constructor.
In other words, we’re talking about derived class specific base construction.
Marshall Cline called that “Dynamic Binding During Construction”, and it’s problematic in C++ because in C++ the dynamic type of an object during class T construction and destruction, is T. This helps with type safety, in that a virtual member function is not called on a derived class sub-object before that sub-object has been initialized, or its initialization has started. But a major cost is that DBDI (apparently) can’t be done in a way that is both simple and safe.
Where the derived class specific init can be performed.
In the question the derived class specific action is called read. Here I call it derived_action. There are 3 main possibilities for where the derived_action is invoked:
Invoked by instantiation code, called two-phase construction.
This essentially implies the possibility of having a mostly unusuable not fully initialized object at hand, a zombie object. However, with C++11 move semantics that has become more common and accepted (and anyway it can be mitigated to some extent by using factories). A main problem is that during the second phase of construction the ordinary C++ protection against virtual calls on uninitialized sub-objects, due to dynamic type changes during construction, is not present.
Invoked by Derived constructor.
For example, derived_action can be invoked as an argument expression for the Base constructor. A not totally uncommon technique is to use a class template to generate most derived classes that e.g. supply calls of derived_action.
Invoked by Base constructor.
This implies that knowledge of derived_action must be passed up to the constructor, dynamically or statically. A nice way is to use a defaulted constructor argument. This leads to the notion of a parallel class hierarchy, a hierarchy of derived class actions.
This list is in order of increasing sophistication and type safety, and also, to the best of my knowledge, reflects the historical use of the various techniques.
E.g. in Microsoft’s MFC and Borland’s ObjectWindows GUI early 1990’ libraries two-phase construction was common, and that kind of design is now, as of 2014, regarded as very ungood.
This is the factory method approach, putting the factory into the base class:
class A {
public:
virtual void read() = 0;
template<class X> static X* create() {X* r = new X;X->read();return X;}
virtual A* clone() const = 0;
};
class B : public A {
B():A() { };
friend class A;
public:
void read() { /*Do something special for B here.*/ }
B* clone() const {return new B(*this);}
};
class C : public A {
C():A() { };
friend class A;
public:
void read() { /*Do something special for C here.*/ }
C* clone() const {return new C(*this);}
};
Added a clone-method with covariant return type as a bonus.
Using CRTP:
class A {
public:
// This never needs to be called
virtual void read() = 0;
virtual A* clone() const = 0;
};
template<class D, class B> struct CRTP : B {
D* clone() {return new D(*this);}
static D* create() {return new D();}
};
class B : public CRTP<B, A> {
B() { };
public:
void read() { /*Do something special for B here.*/ }
};
class C : public CRTP<C, A> {
C() { };
public:
void read() { /*Do something special for C here.*/ }
};
One way to achieve this, would be simply to delegate it to another class (that is perhaps a friend) and can be sure to be called when fully constructed.
class A
{
friend class C;
private:
C& _c; // this is the actual class!
public:
A(C& c) : _c(c) { };
virtual ~A() { };
virtual void read() = 0;
};
class B : public A
{
public:
B(C& c) : A(c) { };
virtual ~B() { };
virtual void read() {
// actual implementation
};
};
class C
{
private:
std::unique_ptr<A> _a;
public:
C() : _a(new B(*this)) { // looks dangerous? not at this point...
_a->read(); // safe now
};
};
In this example, I just create a B, but how you do that can depend on what you want to achieve and use templates on C if necessary, e.g:
template<typename VIRTUAL>
class C
{
private:
using Ptr = std::unique_ptr<VIRTUAL>;
Ptr _ptr;
public:
C() : _ptr(new VIRTUAL(*this)) {
_ptr->read();
};
}; // eo class C
The workaround is to call the virtual function after construction. You can then couple the two operations (construction + virtual call) in factory function. Here is the basic idea:
class FactoryA
{
public:
A *MakeA() const
{
A *ptr = CreateA();
ptr->read();
return ptr;
}
virtual ~FactoryA() {}
private:
virtual A *CreateA() const = 0;
};
class FactoryB : public FactoryA
{
private:
virtual A *CreateA() const { return new B; }
};
// client code:
void f(FactoryA &factory)
{
A *ptr = factory.MakeA();
}
As mentioned by Benjamin Bannier, you can use CRTP (a template which defines the actual read() function.) One problem with that method is that templates have to always be written inline. That can at times be problematic, especially if you are to write really large functions.
Another way is to pass a function pointer to the constructor. Although, in a way, it is similar to calling the function in your constructor, it forces you to pass a pointer (although in C++ you could always pass nullptr.)
class A
{
public:
A(func_t f)
{
// if(!f) throw ...;
(*f)();
}
};
class B : A
{
public:
B() : A(read) {}
void read() { ... }
};
Obviously, you have the "can't call other virtual functions" problem within the read() function and any function it calls. Plus, variable members of B are NOT yet initialized. That is probably a much worst problem in this case...
For that reason, writing it this way is safer:
B() : A()
{
read();
}
However, in cases like that, that may be the time when you an some for of init() function. That init() function can be implemented in A() (if you make it accessible: i.e. use public A when deriving) and that function can call all the virtual functions as expected:
class A
{
public:
void init()
{
read();
}
};
class B : public A
{
public:
...
};
I know a lot of people say that an init() function is evil because people who create a B object now need to know to call it... but there isn't much else you can do. That being said, you could have a form of factory, and that factory can do the init() call as required.
class B : public A
{
public:
static B *create() { B *b(new B); b->init(); return b; }
private:
B() { ... } // prevent creation without calling create()
};

boost shared_from_this and multiple inheritance

I am currently having some troubles when using boost enable_shared_from_this and multiple inheritance.
The scenario can be described as follows:
Class A implements some functionality and should inherit from enable_shared_from_this
Class B implements another functionality and should inherit from enable_shared_from_this
Class D inherits functionalities from A and B (class D : public A, public B {})
When using some class B functionality from class D I got an exception (bad_weak_ptr)
To inherit enable_shared_from_this from class D is not an option for me
I am not sure about how to solve this.
Oh, I am using Visual C++ 2010.
Expanding on Potatoswatter's solution, if you can change A and B to use a something slightly different than enable_shared_from_this. The code uses the standard library versions, but the boost implementation should be similar. Explanation below
#include <memory>
template<typename T>
struct enable_shared_from_this_virtual;
class enable_shared_from_this_virtual_base : public std::enable_shared_from_this<enable_shared_from_this_virtual_base>
{
typedef std::enable_shared_from_this<enable_shared_from_this_virtual_base> base_type;
template<typename T>
friend struct enable_shared_from_this_virtual;
std::shared_ptr<enable_shared_from_this_virtual_base> shared_from_this()
{
return base_type::shared_from_this();
}
std::shared_ptr<enable_shared_from_this_virtual_base const> shared_from_this() const
{
return base_type::shared_from_this();
}
};
template<typename T>
struct enable_shared_from_this_virtual: virtual enable_shared_from_this_virtual_base
{
typedef enable_shared_from_this_virtual_base base_type;
public:
std::shared_ptr<T> shared_from_this()
{
std::shared_ptr<T> result(base_type::shared_from_this(), static_cast<T*>(this));
return result;
}
std::shared_ptr<T const> shared_from_this() const
{
std::shared_ptr<T const> result(base_type::shared_from_this(), static_cast<T const*>(this));
return result;
}
};
So, the intent is that struct A would inherit publicly from enable_shared_from_this_virtual<A> and struct B would inherit publicly from enable_shared_from_this_virtual<B>. Since they both share the same common virtual object, there is only one std::enable_shared_from_this in the hierarchy.
When you call either classes shared_from_this, it performs a cast from enable_shared_from_this_virtual<T>* to T*, and uses the aliasing constructor of shared_ptr so that the new shared_ptr points to T* and shares ownership with the single shared pointer.
The use of the friend at the top is to prevent anyone from accessing the shared_from_this() members of the virtual base directly. They have to go through the ones provided by enable_shared_from_this_virtual<T>.
An example:
#include <iostream>
struct A : public enable_shared_from_this_virtual<A>
{
void foo()
{
shared_from_this()->baz();
}
void baz()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct B : public enable_shared_from_this_virtual<B>
{
void bar()
{
shared_from_this()->baz();
}
void baz()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct D: A, B {};
int main()
{
std::shared_ptr<D> d(new D);
d->foo();
d->bar();
return 0;
}
A shared_ptr is an observer to an invisible container object, or "control block." This container is always on the heap, never on the stack, and you can't get direct handle on it. Although shared_ptr and weak_ptr provide the only means of observation, there is still a hidden layer which owns the object. It is that hidden layer which populates enable_shared_from_this.
Multiple inheritance from enable_shared_from_this is not allowed because all the enable_shared_from_this bases would need to be initialized individually, but the control block has no way of getting a list of all base subobjects of a given type. All it can get is an ambiguous base error.
The only solution I see is to add a virtual base class of A and B which inherits from enable_shared_from_this. You might designate a particular class for this purpose:
struct shared_from_this_virtual_base
: std::enable_shared_from_this< shared_from_this_virtual_base >
{};
struct shared_from_this_base : virtual shared_from_this_virtual_base {};
struct A : shared_from_this_base { … };
struct B : shared_from_this_base { … };
But, there's another problem: you can't down-cast from a virtual base because it's ambiguous whether A or B contains the shared_from_this_virtual_base. To recover an A* or B* you would have to add those pointers to some kind of registry structure within shared_from_this_virtual_base. This would probably be populated by adding another CRTP pattern to shared_from_this_base. It's a bit more footwork than usual for C++ but I don't see any conceptual shortcut.
EDIT: Ah, the simplest way to get the downcast is to put a void* member in shared_from_this_virtual_base and then cast that to D* in whatever client code has knowledge of D. Quite workable, if not perfectly elegant. Or boost::any could provide a safer alternative.
The standard is a bit vague about how shared_from_this is supposed to be implemented, but all implementations seem to agree, because Boost provides a reference implementation.
When you create boost::shared_ptr<D> myD(new D()) the shared_ptr constructor checks if there is an unambiguous conversion from D* to enable_shared_from_this<X>* for some X (which implies that D has a base class of type enable_shared_from_this<X>). If the conversion works then a weak_ptr<X> in the base class will be set to refer to the newly-created shared_ptr.
In your code there are two possible conversions, to enable_shared_from_this<A> and enable_shared_from_this<B>, which is ambiguous, so no weak_ptr gets set to refer to myD. That means if a member function of B later calls shared_from_this() it will get a bad_weak_ptr exception, because its enable_shared_from_this<B> member was never set.

why shared_ptr can access with ingoring the "protected access right"

I made some testing with shared_ptr,and i can't think out the matter below.I just started to learn the boost library. Is there anybody can tell me the reason?
#include <boost\shared_ptr.hpp>
#include <iostream>
class A
{
public:
virtual void sing()
{
std::cout<<"A";
}
protected: virtual ~A() {};
};
class B : public A
{
public:
virtual void sing()
{
std::cout << "B";
}
virtual ~B() {};
};
int foo()
{
boost::shared_ptr<A> pa(new B());
pa->sing();
delete static_cast<B*>(pa.get());
delete pa.get(); //this line has a problem error C2248: “A::~A”: can't access protected memmber(declared in class“A")
return 0;
}
int main()
{
foo();
return 0;
}
but it can be compiled when that line is commented out. Surely it doesn't mean that the shared_ptr will delete the pointer internally maintained out of the main function, just like what i did. Is there any difference between the pointer returned by pa.get() and the pointer internally maintained?
I believe that delete is called during destruction of the shared_ptr on the type of the pointer passed into the constructor. Have a look at the constructor here:
http://www.boost.org/doc/libs/1_49_0/libs/smart_ptr/shared_ptr.htm#constructors
So when your pa goes out of scope, B::~B( ) is called rather than the destructor of the type contained - A::~A ( which would be impossible because it's declared protected).
Actually, it's a bit more complicated than that: the machinery behind shared_ptr is quite complicated.
First, let us prove there is no specific access rights granted to shared_ptr:
int main() {
A* a = new B();
std::shared_ptr<A> p(a); // expected-error
}
This will result in an error because the destructor of A is not accessible. Interestingly, the error occurs at the point of construction, which is a clue...
So, what is the magic behind shared_ptr ?
Internally, a shared_ptr keeps much more than a simple pointer and reference counts. A shared_ptr is built with a deleter, in charge of destructing the instance of the object. Where the design really shines is that this deleter is instantiated in the constructor and thus may know more type information than the bare shared_ptr type lets on.
A simplified demo:
template <typename T>
struct shared_holder {
typedef void (*Disposer)(T*);
explicit shared_holder_base(T* t, Disposer d): _ptr(t), _disposer(d) {}
void dispose() { _disposer(_ptr); _ptr = 0; }
T* _ptr;
Disposer _disposer;
};
template <typename U, typename T>
void dispose(T* t) { delete static_cast<U*>(t); }
template <typename T>
class shared_ptr {
typedef shared_holder<T> holder;
public:
shared_ptr(): _holder(0), _ptr(0) {}
template <typename U>
explicit shared_ptr(U* u):
_holder(new holder(u, dispose<U, T>)), _ptr(_holder->_ptr) {}
private:
holder* _holder;
T* _ptr;
};
The key insight is that the disposer is instantiated from the static type known by the constructor; this is why:
shared_ptr<A>(new B) works
A* a = new B; shared_ptr<A>(a) does not
You can read the Boost headers, the machinery behind the shared_ptr is quite interesting.
As an exercise for the reader, why does shared_ptr<T> has a _ptr member ?
When you have:
boost::shared_ptr<A> pa(new B());
...you are calling boost::shared_ptr constructor and are dealing with TWO template parameters:
shared_ptr template type T (A in your case);
get() returns T* so when you tried:
delete pa.get();
...you tried to access ~A() which is accessible only to As children and therefore got an error.
In the following line:
delete static_cast<B*>(pa.get());
...you were downcasting A* to B* and called delete on B* thus invoking ~B() to which you had access. (~B() is always calling ~A() for ~A() is declared as virtual)
shared_ptr constructor argument template type Y (B in your case) with the
requirement that Y* must be convertible to T* (you can upcast
B* to A* as B inherits A in your case).
~shared_ptr() calls delete on Y* (B* in your case; ~B() can access ~A() and
calls it) and this is what happens when pa goes out of scope (and this is how shared_ptr accessed base class protected destructor which was your original question).
boost::shared_ptr keeps internally a single pointer. When creating boost::shared_ptr you are passing to its constructor a SINGLE pointer which can be regarded as / converted to pointer to any of those TWO template argument types.
I believe it is because the definition of the boost template declares the sharedpointer a friend of the <Class T> class from your template instantiation.
This is a snipet I copied from the boot shared pointer header file.
// Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston)
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private:
template<class Y> friend class shared_ptr;
template<class Y> friend class weak_ptr;
#endif

boost::dynamic_pointer_cast returning null on valid cast

I'm using boost::shared_ptr's and boost::dynamic_pointer_cast. I have a base class, an interface that inherits from that base class, and then a class that inherits from that one.
So A -> B -> C. I create an object of type C and it's stored as a shared_ptr of type A. Then I try and do a dynamic_pointer_cast to type B, but boost::dynamic_pointer_cast returns NULL.
When I do a boost::static_pointer_cast and use the pointer, it doesn't crash the program. But I would prefer if the dynamic cast worked.
Why is this happening?
EDIT: Here's a compact section of the code (otherwise it's too long to put here). Tell me if you need more than the header files.
class A
{
public:
virtual ~A();
/** Contains other virtual functions and some static functions */
protected:
A();
};
class B
{
public:
/** Pure virtual functions */
/** Note: No destructor is declared (when I next have
access to the computer I'll try adding a virtual destructor) */
protected:
B();
};
class C
{
public:
C();
virtual ~C();
/** Implementation of pure virtual functions */
};
Also, the dynamic_pointer_cast for this same code works on another computer with the exact same classes. Which has me at a complete loss. The code also worked until about a week ago when I made a change. When I reverted the change, the problem still occurred.
Some code would help. The obvious first guess is that perhaps you forgot to give A a virtual destructor.
It's hard to say without your definitions of A, B, and C, along with your usage.
Compare your program to the following:
#include <boost/shared_ptr.hpp>
#include <iostream>
struct A { virtual ~A() {} };
struct B : A {};
struct C : B {};
int main()
{
boost::shared_ptr<A> x(new C);
boost::shared_ptr<B> y(boost::dynamic_pointer_cast<B>(x));
std::cout << std::boolalpha
<< (y.get() != 0) << std::endl;
}

C++ Puzzle: Prevent heap allocation for derived classes, allow automatic and static

Objectives:
Objects of class Base may be static, automatic, allocated directly on the heap, and take part in composite objects allocated anywhere
For any class Derived which has Base as an accessible ancestor, objects may be static or automatic and take part in composites, but may not be allocated directly on the heap
Example:
#include "Base.h"
#include "Derived.h"
{
static Base sb; // OK
Base ab, *hb = new Base; // OK
static Derived sd; // OK
Derived ad; // OK
Derived *pd = &ad; // OK
Derived *hd = new Derived; // Compile error, link error,
// test-unit exception, or lint gripe
struct Composite {
Base cb;
Derived cd;
} *hc = new Composite; // OK
// Edit to show side-effects of solutions which hide Base::operator new.
std::vector<Base> vb; // OK
std::vector<Derived> vd; // Error
// ...
}
How could Base be implemented to achieve this? A compile-time error is preferred to a link-time error; but although both are preferred to a test-unit exception, and a test-unit exception is preferred to a lint gripe, any solution that does not require an update to Base.h for each derivation will do.
Edit: For the purposes of this question, solutions which involve forking the compiler so that it supports arbitrary decorations are, despite the technical challenge, classified as "trivial."
Hmm, Eclipse's answer is gone, but I thought it was on the right track.
class Base {
public:
static Base *create() { return new Base; }
static Base *create(size_t n) { return new Base[n]; }
private:
// Prevent heap allocation
void *operator new(size_t s);
void *operator new[](size_t s);
};
This isn't nice, as it obligates you to use Base::create() instead of new Base, and class Derived could still go and implement its own public operator new, but I think it's workable.
I feel bad for stealing ephemient's thunder here, but the only thing "wrong" with his answer is that he's made Base's operator new private, and not Derived's:
The following code compiles except for the last line, which I think is what you require:
#include <new>
#include <vector>
class Base {};
class Derived : public Base {
private:
void * operator new (size_t);
};
void foo ()
{
static Base sb; // OK
Base ab, *hb = new Base; // OK
static Derived sd; // OK
Derived ad; // OK
Derived *pd = &ad; // OK
struct Composite {
Base cb;
Derived cd;
} *hc = new Composite; // OK
std::vector<Base> vb; // OK
std::vector<Derived> vd; // OK
Derived *hd = new Derived; // Compile error
}
UPDATE:
As Tal points out, you can still call "new Derived" from a static member of Derived, however by not defining the "operator new" this will result in a link error.
But you can change the code slightly so that it generates a compile error (which is always preferable). We can declare a placement operator new that will still stop us calling the usual operator new.
class Derived : public Base {
public:
static Derived * create ()
{
return new Derived;
}
private:
class dont_dynamically_allocate_type_derived;
void * operator new (size_t, dont_dynamically_allocate_type_derived);
};
Using g++, the the above generates:
t.cc: In static member function static Derived* Derived::create():
t.cc:10: error: no matching function for call to Derived::operator new(unsigned int)
t.cc:15: note: candidates are: static void* Derived::operator new(size_t, Derived::dont_dynamically_allocate_type_derived)
UPDATE (part duex):
I cannot think of any construct where a base class propagates a property that it itself doesn't also have. Tweaking the requirements slightly, if it's allowed to add an extra layer of inheritance you can create two leaf classes, one for Base the type that will be used to instantiate Base objects, and the other that is inherited from:
class Base
{
public:
private:
friend class BaseInstance;
friend class BaseDerived;
~Base () {}
};
class BaseInstance : public Base
{
public:
~BaseInstance () {}
};
class BaseDerived : public Base
{
public:
~BaseDerived () {}
private:
static void * operator new (size_t);
static void * operator new[] (size_t);
};
class Derived : public BaseDerived {
public:
static Derived * create ()
{
return new Derived;
}
};
There is still a problem that people can derive from "BaseInstance", although it's name could be made explicitly to stop that happening. There's also the possibility that that class is on the other side of an API and so clients only ever get to see "BaseDerived".
While there are ways to "discourage" heap allocation of an object in code (several good ones discussed and linked to here), there is no way to fully prevent it. There are some types such as shared_ptr<T> that I generally never want heap allocated (or perhaps a variant that I truly never want heap allocated). For these, the absolute best solution is understanding and documenting why you never want them heap allocated. With that in place, we never ran into problems because we were consistent about it.
how about privately derive Base?
class Base {
public:
void *operator new(size_t);
};
class Derived : private Base {
public:
};
Here's one solution I found on the web:
Another standard new, the so-called "placement-new," doesn't allocate memory at all, but can be called to invoke an object's constructor on an arbitrary piece of memory. It is typically defined as:
inline void *
operator new(size_t, void *p)
{
return p;
}
From http://www.scs.stanford.edu/~dm/home/papers/c++-new.html .