为什么派生类可以具有与基类相同的数据成员
Why can the derived class have the same data members from the base class?
由于基类和派生类中都有相同的数据成员,这会造成很多混乱,并且需要使用范围解析运算符来解决冲突。那么,为什么它在C++中被允许呢?有人能告诉我需要这个吗?
我不知道确切的动机,但我相信这是少数类似情况的简单扩展,在这些情况下这是不可避免的。例如,考虑多个继承——许多基类可能具有相同的成员,作为派生类的创建者,基本上对此无能为力。对于CRTP来说更糟糕的是,您不可能知道基类的成员,因为它是任意的。这些案例似乎没有你问题的主题那么令人困惑,而且问题更大,因为在不削弱某些功能的情况下,不能简单地禁止它们。既然无论如何都必须解决歧义问题,那么用同样的统一规则来处理这个特定的案例似乎是很自然的。
阴影并不总是坏的。阴影非常重要的一个反例是当我们使用可变模板(尤其是元组)时
示例:考虑以下过于简化的元组实现。这是我看到的第一个如何使用可变模板的例子。
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;
}
在这里你可以看到,如果没有阴影,使用可变模板会更加困难。此外,get<>std::tuple中的方法也有类似的实现。
在合理的设计中,这不应该是一个问题。如果您有意创建与基础名称相同的成员,则您的设计存在问题。如果您在不知不觉中这样做,您将不会注意到。
另一方面,如果这在语言层面被禁止,他们在不知不觉中部分将成为一个严重的错误。考虑使用从中继承的框架。现在考虑一下,有一个公共接口是有文档记录的,但任何私有的都是没有文档记录的。现在,您需要从一个类型(比如Window
)继承,并且您有了这个变量,它有一个漂亮而有意义的名称,这在世界上是有意义的。如果将其添加到类型中,运行编译器只会发现该名称已在基类型中(或层次结构中的某个位置)使用。。。
- 如何基于模板化类的基类专门化成员函数
- 为什么基类数据在派生类数据之前初始化
- 重写函数不打印基类数据
- 继承:调用基类的成员和方法
- 将基类的成员函数重载到其他派生类C++
- C++ 使用派生类方法更改基类数据成员
- 不可复制类数据成员的统一初始化导致gcc错误
- 派生类不能用另一个基类的成员重载基类中的私有成员
- 是否可以访问类数据成员并在析构函数中对它们执行操作?
- 基类私有成员属于派生类的哪个部分?
- 在不编写显式 setter 的情况下修改私有类数据成员的便捷方法是什么?模板有用吗?
- 不能从派生类中获取基类的成员. C++
- 基类数据成员类型取决于派生类
- 使用来自基类方法的派生类数据成员
- C++-填充派生类数据成员,同时设置基类属性值
- 仅授予派生类对基类数据成员/函数的 const 访问权限
- 具有继承的桥接设计模式,其中抽象基类具有成员数据
- 在派生类成员初始化列表中初始化基类数据成员时出现c++错误
- 从派生类对象调用基类函数.派生类构造函数中设置的基类数据成员
- 我如何通过基类指针获得派生类数据成员(向上转换)