防止派生类向基类强制转换

7

I have

class Rect{
   // stuff
};

并且

class SpecialRect:public Rect{
private:
     operator const Rect(){return *this;}          // No implicits casts to Rect
public:
     // stuff
};

SpecialRect继承自Rect的所有属性和方法,但我希望避免将SpecialRect隐式转换为基类Rect。

在代码中:

SpecialRect oneSpecial;
Rect aRect=oneSpecial;          // I want this to not compile. (to remind-me to declare aRect as SpecialTect)

编译没有错误。(我知道将基类Rect声明为私有可以实现,但我不想重新实现它的所有方法。)

有什么方法可以实现这个效果吗?


4
基本上就像是问“如何防止我的猫成为动物”,你为什么要防止呢?这似乎是有缺陷的设计。 - David Haim
2
你违反了旧的“是一个”规则:你的特殊矩形不是矩形。 - user2249683
你可能想要了解一下Liskov替换原则 - TartanLlama
3
@DavidHaim:正如所述,OP希望禁止对象切片 - Jarod42
顺便提一下,自从C++11以来,使用=delete;比没有实现的private更好地禁止某些操作(即使您错误地提供了一个)。 - Jarod42
显示剩余2条评论
1个回答

7
在Rect中声明SpecialRect的私有复制构造函数可以解决问题,但有一个缺点:Rect依赖于SpecialRect的声明。【来自Jarod42的评论】
注意:请记住实现空的构造函数,因为不会有默认构造函数。
class SpecialRect;

class Rect {
public:
    Rect(){}

private:
    Rect(const SpecialRect&);
    //Rect(const SpecialRect&) = delete; // c++11
};

class SpecialRect : public Rect {

};


int main()
{
    SpecialRect sr;
    //Rect r1 = sr; // error: 'Rect::Rect(const SpecialRect&)' is private
    //Rect r2(sr); // error: 'Rect::Rect(const SpecialRect&)' is private

    Rect r3;
    Rect r4(r3);
    Rect r5 = r3;
    return 0;
}

另一个解决方案是在 Rect 中声明 显式默认复制构造函数。这种方法的好处在于不依赖于子类,但会带来副作用。

class Rect {
public:
    Rect(){}
    explicit Rect(const Rect&);
};

class SpecialRect : public Rect {

};

int main()
{
    SpecialRect sr;
    //Rect r1 = sr; // Prevents this
    Rect r2(sr);    // Leaves this

    Rect r3;
    Rect r4(r3);
    //Rect r5 = r3;  // Side Effect: Prevents this

    return 0;
}

3
但是 Rect r(sr) 仍然可行。Rect(const SpecialRect&) = delete; 是一种替代方法。 - Jarod42
2
在C++11中,使用=delete;比旧的C++03 private没有实现更好。 - Jarod42
1
首先,具有“显式”复制构造函数的答案具有其优点:它简单且不依赖于子类。 - Jarod42
1
但是在这两种情况下,您仍然可以将其转换为Rect类型!Rect&rect = static_cast<Rect&>(sr); 证明1:http://coliru.stacked-crooked.com/a/449d533279215d62。 证明2:http://coliru.stacked-crooked.com/a/3f909a9df3cf9a78 - tower120
1
问题的标题有误导性。@Joan 在他的问题中所描述的是他需要防止将派生对象复制到基本对象。这就是答案所涉及的内容。 - Meena Alfons
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接