2

由于在基类和派生类中具有相同的数据成员,它会造成很多混乱,并且需要使用范围解析运算符来解决冲突。那么为什么在 C++ 中允许它呢?任何人都可以告诉我需要这个吗?

4

3 回答 3

4

我不知道确切的动机,但我相信这是少数类似案例的简单延伸,这是不可避免的。例如,考虑多重继承 - 许多基类可能具有相同的成员,并且作为派生类的创建者,您基本上无能为力。对于 CRTP 来说更糟糕的是——你不可能知道基类的成员,因为它是任意的。这些案例似乎没有您的问题主题那么令人困惑,而且问题更大,因为不能简单地禁止它们而不削弱某些功能。由于无论如何都必须解决歧义问题,因此使用相同的统一规则处理这种特殊情况似乎是很自然的。

于 2013-08-30T18:45:41.293 回答
2

遮蔽并不总是坏事。阴影非常重要的一个反例是当我们使用可变参数模板(尤其是元组)时

示例:考虑以下元组的过度简化实现。这是我看到如何使用可变参数模板的第一个示例。

template<typename... T> class tuple0;

template<> class tuple0<> {}; // end recursion

template<typename Head, typename... Tail>
 class tuple0<Head, Tail...> : public tuple0<Tail...> {
 public:
 Head head;
};

假设现在我们要创建tuple0<int, double>和访问这两个元素。这是一个执行此操作的测试程序

int main()
{    
    tuple0<int, double>* t1  = new tuple0<int, double>;
    t1->head = 7; //  set the integer value
    std::cout << "integer: " << t1->head << std::endl; 
    tuple0<double>* t2 = static_cast< tuple0<double>* >(t1);
    t2->head = std::cos(2);  // set the double value
    std::cout <<  "double: " << t2->head << std::endl;
    return 0;
}

在这里您可以看到,如果没有遮盖,使用可变参数模板会更加困难。此外,std::tuple 中的 get<> 方法也有类似的实现。

于 2013-08-30T19:37:01.253 回答
1

在一个明智的设计中,这不应该是一个问题。如果您故意创建与您的基地同名的成员,那么您的设计就有问题。如果您在不知不觉中这样做,您将不会注意到。

另一方面,如果这在语言层面被禁止,他们不知不觉的部分将成为一个硬错误。考虑使用您从中继承的框架。现在考虑有一个有据可查的公共接口,但任何私有的都是无证的。现在你需要从一个类型(比如 a Window)继承,并且你拥有这个变量,这个变量有一个美丽而有意义的名字,这在世界上都是有意义的。您将其添加到您的类型中,运行编译器只是发现该名称已在基本类型(或层次结构中的某个位置)中使用...

于 2013-08-30T19:26:13.647 回答