继承时的变量范围

时间:2009-11-05 17:37:11

标签: c++ inheritance scoping

我在C ++中有两个类,其中一个继承自另一个:

class A {
public: 
    virtual void Initialize(){
        m_MyString = "Default value";
    }

protected: 
     string m_MyString;
}

class B : public A {
public: 
    void Initialize(){ 
       A::Initialize(); 
       m_MyString = "New Value";
    }
}

上述B级与此之间有区别吗?

class B : public A {
public: 
    void Initialize(){ 
       A::Initialize(); 
       A::m_MyString = "New Value";
    }
}

看起来使用作用域操作符会导致字符串有垃圾,对吗?我想当它覆盖时,A :: m_MyString与B :: m_MyString不同。这甚至有意义吗?

我看到变量在A中设置,然后当我们返回B时,有垃圾。这与“隐藏”与被覆盖有关吗?

6 个答案:

答案 0 :(得分:1)

您的代码在许多方面无效。它应该看起来像:

class A { // << errors were here
public: 
    virtual void Initialize(){
        m_MyString = "Default value";
    }

protected: 
     string m_MyString;
}; // << lost ;

class B : public A // << errors were here
{
public: 
    virtual void Initialize(){  // << virtual
       A::Initialize(); // has no effect in the end

       A::m_MyString = "New Value"; // same as `m_MyString = "New Value";`
    }
}; // << lost ;

在上面的代码中,与m_MyString没有区别。发布错误的实际代码。

如果你的代码如下:

class B : public A
{
public: 
    virtual void Initialize(){
       // here is a difference
       A::m_MyString = "New Value"; 
       m_MyString = "New Value";
    }
protected: 
     string m_MyString; // !!! overridden
};

然后存在差异,因为B有两个m_MyString实例:A::m_MyStringB::m_MyString

答案 1 :(得分:1)

你是否从A的构造函数中调用Initialize()?

不建议在构造函数中调用虚方法。例如,如果A的构造函数看起来像

A::A() {
  Initialize();
}

B的Initialize方法永远不会被调用。

查看您的实际代码会有很大帮助。

答案 2 :(得分:0)

这两个版本的B类没有区别。这是你看到垃圾的真实代码吗?

答案 3 :(得分:0)

编译器应该告诉您是否从构造函数调用虚函数。但如果没有,那肯定是个问题。

我认为你可以在派生类中创建一个虚函数final,但也许不是。无论是否明确定义范围,变量都应该相同,除非在派生类中有一个同名变量。

答案 4 :(得分:0)

如果这是你的代码的样子:

using namespace std;

class A 
{
    public:
        virtual void Initialize()
        {
            m_MyString = "Default value";
        }

    protected:
        string m_MyString;
};

class B : public A 
{
    public:
        void Initialize()
        {
            A::Initialize();
            m_MyString = "New Value";
        }

        void display()
        {
            cout<<m_MyString<<endl;
        }
};

int main()
{
    B b;
    A a;

    b.Initialize();
    b.display();

    return 0;
}

然后,您在问题中描述的B类的两个版本之间没有区别。我添加了显示功能只是为了使值清晰。根据您给出的类的定义,不会覆盖m_MyString。因此,m_MyString变量将为其分配“新值”,即类A和B都将共享变量m_MyString。

如果覆盖类B中的m_MyString,如

class B : public A 
{
    public:
        void Initialize()
        {
            A::Initialize();
            m_MyString = "New Value";
        }

    void display()
    {
        cout<<m_MyString<<endl;
    }

    protected:
        string m_MyString;
};

然后B :: m_MyString的值将包含“New Value”,A :: m_MyString的值将包含“Default value”。

答案 5 :(得分:0)

  
    

看起来使用作用域操作符会导致字符串有垃圾,对吗?

  

不,这应该有效,并且在调用b.Initialize()之后m_MyString将具有“新值”。

  
    

我在想它覆盖时,A :: m_MyString与B :: m_MyString不同。是否     这甚至有意义吗?

  

不,当B类继承另一个A类时,B类的对象将具有两者的数据成员的并集。在这种情况下,只有一个m_MyString是A :: m_MyString。

  
    

我看到变量在A中设置,然后当我们返回B时,有垃圾。     这与“隐藏”与被覆盖?

有关   

不,只有一个m_MyString实例。

您肯定需要阅读此内容 - http://www.openrce.org/articles/files/jangrayhood.pdf