2

我在 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 时,有垃圾。这与“隐藏”与覆盖有关吗?

4

6 回答 6

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.

于 2009-11-05T17:56:01.827 回答
1

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

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

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

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

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

于 2009-11-05T17:58:51.143 回答
0

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

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

于 2009-11-05T18:02:55.783 回答
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 的值将包含“新值”,而 A::m_MyString 的值将包含“默认值”。

于 2009-11-05T18:22:22.803 回答
0

这两个版本的 B 类之间没有区别。那是您在其中看到垃圾的真实代码吗?

于 2009-11-05T17:44:57.257 回答
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

于 2009-11-05T18:42:10.360 回答