为什么这个指针需要访问继承的属性?

时间:2010-12-22 15:26:49

标签: c++ inheritance

假设给出以下类:

class Base{
public:

Base() {}
Base( const Base& b) : base_attr(b.base_attr) {}

void someBaseFunction()
{ .... }

protected:

SomeType base_attr;
};

当我希望一个类从这个继承并为派生类包含一个新属性时,我会写:

class Derived: public Base {
public:

Derived() {}
Derived( const Derived& d ) : derived_attr(d.derived_attr)
{
  this->base_attr = d.base_attr;
}

void SomeDerivedFunction()
{ .... }

private:

SomeOtherType derived_attr;
};

这对我有用(让我们忽略最后丢失的分号或者这样)。

然而,当我删除“this->”时在派生类的复制构造函数中,编译器抱怨“'base_attr'未在此范围内声明”。

我认为,当从类继承时,受保护的属性也可以直接访问。我不知道“这个 - >”指针是必需的。 我现在很困惑,如果它实际上是正确的,我在那里做的,特别是Derived-class的复制构造函数。

因为每个Derived对象都应该有base_attr和derived_attr,所以显然需要正确初始化/设置它们。 因为Derived继承自Base,所以我不想在Derived-class中显式包含名为“base_attr”的属性。恕我直言这样做通常会破坏继承背后的想法,因为一切都必须再次定义。


修改

谢谢大家的快速解答。我完全忘记了类实际上是模板的事实。

请参阅下面的新示例,这些示例在包含“this->”时实际编译省略“this->”时失败在Derived-class的copy-constructor中: 基类:

#include <iostream>

template<class T> 
class Base{
public:

Base() : base_attr(0) {} 
Base( const Base& b) : base_attr(b.base_attr) {} 

void baseIncrement()
{ ++base_attr; }

void printAttr()
{
        std::cout << "Base Attribute: " << base_attr << std::endl;
}

protected:

 T base_attr;
};

派生类:

#include  "base.hpp"

template< class T >
class Derived: public Base<T>{
public:

Derived() : derived_attr(1) {} 
Derived( const Derived& d) : derived_attr(d.derived_attr)  {  
        this->base_attr = d.base_attr;
        }  

void derivedIncrement()
{ ++derived_attr; }

protected:

 T derived_attr;
};

并且完整性也是主要功能:

#include "derived.hpp"

int main()
{
        Derived<int> d; 
        d.printAttr();

        d.baseIncrement();
        d.printAttr();

        Derived<int> d2(d);
        d2.printAttr();

        return 0; 
};

我正在使用g ++ - 4.3.4。 虽然我现在理解它似乎来自我使用模板类定义的事实,但我不太明白在使用模板时导致问题的原因以及为什么它在不使用模板时有效。有人可以进一步澄清一下吗?

4 个答案:

答案 0 :(得分:3)

没有理由认为这是必要的。通过this-&gt;隐式访问所有成员变量。我知道没有语言规则规定你应该使用这个 - &gt;访问任何成员函数或变量。

答案 1 :(得分:3)

如果Base在某种程度上依赖于模板参数,那么您才会看到这一点。

在这种情况下,在这样的依赖基类中查找类似base_attr的名称被认为太危险了:对于某些模板实例化,名称可以在基类中找到,对于另一个实例化,该成员可能缺席,名称将引用某个名称空间成员。

因为这被认为是令人困惑的,所以C ++遵循一致的规则,base_attr在进行非限定名称查找时永远不会在依赖基类中查找。您需要在名称前添加this->或者使用Derived<T>::base_attr中的类名称。因此,当基类未声明base_attr时,该名称不会静默引用可能全局声明的名称,但它只是编译时错误。

答案 2 :(得分:1)

我不知道你为什么在没有看到可编译的例子的情况下得到那个错误,但是你可以编写你的拷贝构造函数:

Derived( const Derived& d ) : Base(d.base_attr), derived_attr(d.derived_attr) {}

答案 3 :(得分:0)

您使用的是什么编译器?我没有收到g++的任何错误,也没有看到您列出的代码有任何问题。