const构造函数 [英] Const constructor

查看:149
本文介绍了const构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++中是否有可能实现仅允许创建 const 对象的构造函数之类的东西?

Is it possible in C++ to achieve something like a constructor that is only allowed to create const objects?

我正在考虑使用 const 和非 const 方法将装饰器类制作为接口。从 const 基础对象初始化装饰器只能生成const装饰器,但是从非const初始化应该产生功能齐全的装饰器。

I am thinking of making a decorator class to an interface with const and non const methods. Initializing the decorator from a const base object should only be able to produce const decorators, but initializing from a non-const should yield a fully functional decorator.

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
}

我如何实现类似的效果?

How can I achieve a similar effect?

推荐答案

我只能通过没有返回 const 的构造函数来使此工作正常对象,但返回 shared_ptr< const decorator> 的静态函数(按名称命名的构造函数)。这种编码类型的常量,并禁止非常量调用:

I only was able to get this working by having not a constructor that returns const object, but a static function (a-la named constructor) that returns shared_ptr<const decorator>. This 'encodes' constness in type and prohibits non-const calls:

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获得类似的用法模式。

You can of course use shared_ptr for non-const decorators too by declaring another static function and thus get similar usage patterns for both const and non-const.

将要求您删除副本构造函数和 decorator operator = ,因为它们将失去一致性。但是,在您的版本中,假设的const构造函数也存在类似的问题。

Note that this will require you to delete copy constructor and operator= for decorator, as they will lose constness. However, a similar problem exists in your version with a hypothetical const constructor.

我尝试过的另一种方法是使 decorator 模板类,并具有两种不同的类型: decorator< A> decorator< const A> ,希望除非使用该编译器,否则它不会实例化 decorator< const A> :: foo(),即使不使用它也会实例化。

Another approach that I have tried was to make decorator a template class and have two different types: decorator<A> and decorator<const A>, hoping that compiler will not instantiate decorator<const A>::foo() unless it is used, but it keeps instantiating it even if it is not used.

这篇关于const构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆