防止在 C++ 中调用基赋值运算符

Posted

技术标签:

【中文标题】防止在 C++ 中调用基赋值运算符【英文标题】:Prevent call to base assignment operator in C++ 【发布时间】:2017-09-10 19:48:51 【问题描述】:

我的库中有这两个类:

class Base 
    int _handler;
protected:
    Base() = default;

    Base& operator=(int h) 
        this->_handler = h;
        return *this;
    
;

class Derived : public Base 
protected:
    Derived() = default;

    void initialize() 
        this->Base::operator=(12345); // internal stuff
    
;

Derived 类可供用户继承。他应该这样做:

class User_Class : public Derived 
    void foo() 
        this->initialize();
    
;

但相反,他这样做:

class User_Class : public Derived 
    void foo() 
        this->Base::operator=(999); // no, you broke it!
    
;

如何防止调用Base 赋值运算符?

【问题讨论】:

顺便说一句,this-> 的四种用法都不需要。 我知道,这只是为了清楚起见(即使它足够明显)。谢谢。 您可以将赋值运算符设为私有,然后将Derived 设为Base 的朋友? 你可以使用private(和Derivedfriend)方法... 【参考方案1】:

当我将标题更改为此

class Derived : private Base

编译器立即阻止对 operator= 的调用,并使用“无法访问在类 'Base' 中声明的不可访问成员”,但是调用初始化的代码正常工作,因为它是可访问的。

但是,您还应该在 Derived 中覆盖 operator=,并让它检查它是否已被初始化。不要让客户端类处理内部簿记。

【讨论】:

+1 尤其是最后一句话。不要依赖您的客户知道以正确的顺序调用事物。 补充说明,如果 Derived 中的函数不够用,那就考虑一个接口类,这样他们就知道自己能做什么,不能做什么(编译器也知道)。跨度> @kenny 但是我不能将User_Class 对象传递给void abc(Base& b) 这样的函数,对吧? VC++ 给我错误 C2243:“从 'User_Class *' 到 'Base &' 的转换存在,但无法访问”。 如果你想限制客户端对类内部的访问,那很好,但当然你需要做一些工作来让客户端访问他们真正需要的东西。例如,为什么客户端使用带 Base 的函数?那不应该是 void abc(Derived &d) 吗? 如果他们需要Base私有的一部分和Base公共的一部分,那么将Base分成两个类?我们已经超出了我回答的原始问题的范围。您想要的绝对可以实现,但可能需要重新设计一些面向对象。我们甚至可能不得不使用 virtual 关键字。 :)

以上是关于防止在 C++ 中调用基赋值运算符的主要内容,如果未能解决你的问题,请参考以下文章

C++的探索路12继承与派生之高级篇--派生类与赋值运算符及多重继承

派生类继承基类赋值运算符?

重载赋值运算符 - 多态容器

C++中赋值运算操作符和=重载有啥区别?

C++ 继承多态关系中的赋值运算符的重载=operator()

C++ 继承多态关系中的赋值运算符的重载=operator()