2013-08-30 58 views
2

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

+5

因为一般情况下允许遮阴,对班级没有特别的要求。 –

+1

你的意思是这样吗? http://coliru.stacked-crooked.com/view?id=3d6fa652a3 – Chemistpp

回答

4

我不知道确切的动机,但我相信这是几个类似案例的简单延伸,它是不可避免的。例如考虑多重继承 - 许多基类可能具有相同的成员,并且基本上没有关于它的任何事情可以作为派生类的创建者。 CRTP更糟糕 - 你不可能知道基类的成员,因为它是任意的。这些情况看起来不像你的问题那么容易混淆,而且更麻烦些,因为在不削弱某些功能的情况下不能简单地禁止它们。由于无论如何都必须解决模棱两可的问题,因此用特定的统一规则处理这个特殊情况似乎是很自然的。

+0

还有一些情况下,你明确想要掩盖,就像在可变模板中一样。像C++中的许多其他功能一样,如果使用正确,它可以非常强大。 –

1

在一个明智的设计中,这绝不应该是一个问题。如果你是明知故障创建与你的基地名称相同的成员,这是你的设计有一个问题。如果你不知不觉做到这一点,你不会注意到。另一方面,如果这在语言层面被禁止,他们不知不觉地部分将成为一个硬性错误。考虑使用您继承的框架。现在考虑一下有公共接口,这是有据可查的,但任何私人的都是无证的。现在你需要从一个类型继承(比如说一个Window),并且这个变量带有一个美丽的有意义的名字,这个名字使得世界上的所有感觉都变得有意义。您可以将其添加到您的类型中,只运行编译器以发现名称已用于基本类型(或层次结构中的某处)...

+0

我的印象是,你认为遮遮掩掩从来不是一个好的做法,这是不正确的。在各种模板中,阴影是许多情况下的最佳实践:) –

+0

@ViniciusMiranda:如果那是你的印象,我是一个可怕的作家。遮掩是唯一的*选项,这是有道理的。不仅在泛型代码中,即使在非泛型的纯OO代码中,您可能也需要使用其他代码,并且您甚至可能不知道其数据成员的名称(从文档中,您始终可以阅读标题)。会出现冲突,并且要求避免可能不知道使用的名称,或者升级到新版本的库并且无法编译,因为它们使用了需要重构的新名称,这很奇怪。 –

+0

上一个我给人的印象是你说这是一个不好的习惯,但是不可避免的。我认为现在很清楚。谢谢:) –

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方法也有类似的实现。

+0

这就是为什么我不同意“在合理的设计中,这不应该成为问题”的说法。在可变模板中,遮盖是最佳实践! :) –

+1

+1此示例显示我需要课堂数据成员蒙上阴影 – ZijingWu

+0

您错误地理解了句子*在一个合理的设计中,这永远不应该是一个问题*。虽然我会避免让用户首先访问元组内部(通过提供帮助函数,从而打破了我使用的名称的依赖关系),但这对于get函数是一个明智的设计,并且遮蔽是正确的,因此它不是问题。 –

相关问题