在C ++中是否可以实现类似于只允许创建const
个对象的构造函数?
我正在考虑使用const
和非const
方法为一个接口创建一个装饰器类。从const
基础对象初始化装饰器应该只能生成const装饰器,但是从非const初始化应该会产生一个功能齐全的装饰器。
struct A
{
virtual void foo(); // requires non-const A
virtual void bar() const; // const method
};
class decorator : public A
{
private:
std::shared_ptr<A> p_impl;
public:
virtual void foo() { p_impl->foo(); }
virtual void bar() const { p_impl->bar(); }
// regular constructor
decorator(std::shared_ptr<A> const & p) : p_impl(p) {}
// hypothetical constructor that makes a const
decorator(std::shared_ptr<A const> const & p) const : p_impl(p) {}
};
void F(std::shared_ptr<A> const & regular_a
, std::shared_ptr<A const> const & const_a )
{
decorator regular_decorator(regular_a);
regular_decorator.foo(); // all good
regular_decorator.bar(); // all good
decorator bad_decorator(const_a); // compiler error
// trying to use a const constructor to init a non-const object
const decorator const_decorator(const_a); // all good
const_decorator.foo(); // compiler error, foo is not const
const_decorator.bar(); // all good
// I have a lot of these in code that is beyond my control
decorator bad_practice(const_cast<decorator&>(const_decorator));
bad_practice.foo(); // all good
}
我怎样才能达到类似效果?
答案 0 :(得分:2)
我只能通过没有返回const
对象的构造函数来获得此工作,而是返回shared_ptr<const decorator>
的静态函数(a-la命名构造函数)。这个&#39;编码&#39;类型中的constness并禁止非const调用:
struct A
{
virtual void foo(); // requires non-const A
virtual void bar() const; // const method
};
class decorator : public A
{
private:
std::shared_ptr<A> p_impl;
public:
virtual void foo() { p_impl->foo(); }
virtual void bar() const { p_impl->bar(); }
// regular constructor
decorator(std::shared_ptr<A> const & p) : p_impl(p) {}
static std::shared_ptr<decorator const> constDecorator(std::shared_ptr<A const> const & p) { return std::make_shared<decorator>(std::const_pointer_cast<A>(p)); }
};
void F(std::shared_ptr<A> const & regular_a
, std::shared_ptr<A const> const & const_a )
{
decorator regular_decorator(regular_a);
regular_decorator.foo(); // all good
regular_decorator.bar(); // all good
decorator bad_decorator(const_a); // compiler error
// trying to use a const constructor to init a non-const object
std::shared_ptr<const decorator> const_decorator = decorator::constDecorator(const_a); // all good
const_decorator->foo(); // compiler error, foo is not const
const_decorator->bar(); // all good
// I have a lot of these in code that is beyond my control
decorator bad_practice(const_cast<decorator&>(*const_decorator));
bad_practice.foo(); // all good
}
当然,您也可以通过声明另一个静态函数将shared_ptr
用于非const装饰器,从而获得const和非const的类似使用模式。
请注意,这将要求您删除operator=
的复制构造函数和decorator
,因为它们会丢失常量。但是,您的版本中存在类似的问题,并带有假设的const构造函数。
我尝试过的另一种方法是使decorator
成为模板类,并有两种不同的类型:decorator<A>
和decorator<const A>
,希望编译器不会实例化decorator<const A>::foo()
除非它被使用,但即使没有使用它也会一直实例化。