C++ Puzzle:防止派生类的堆分配,允许自动和静态

Tho*_*day 7 c++

目标:

  1. Base类的对象可以是静态的,自动的,直接在堆上分配,并参与任何地方分配的复合对象
  2. 对于任何具有Base作为可访问祖先的Derived类,对象可以是静态的或自动的并参与复合,但可能不会直接在堆上分配

例:

#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
    // ...
}
Run Code Online (Sandbox Code Playgroud)

如何实现Base来实现这一目标?编译时错误优先于链接时错误; 但是虽然两者都优于测试单元异常,并且测试单元异常优于lint gripe,但任何不需要为每个派生更新Base.h的解决方案都可以.

编辑:出于这个问题的目的,尽管存在技术挑战,但涉及分配编译器以使其支持任意装饰的解决方案被归类为"微不足道".

eph*_*ent 5

嗯,Eclipse的答案已经消失,但我认为它是在正确的轨道上.

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);
};
Run Code Online (Sandbox Code Playgroud)

这不是很好的,因为它责成你使用Base::create()的不是new Base,并且class Derived仍然可以去实现自己的public operator new,但我认为这是可行的.